diff options
author | Martin Polden <mpolden@mpolden.no> | 2024-01-04 13:14:24 +0100 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2024-01-16 10:26:59 +0100 |
commit | 8cf4c07b6ef56cf913e454de2bfa9686520e29dd (patch) | |
tree | 97d6b5f2b94b8fee6a29b118b4324b6b4ec34daf | |
parent | 7a5ed8ea751110afe551d87aaf15582afe5c54c2 (diff) |
fish: port current zsh config
-rw-r--r-- | config.fish | 426 | ||||
-rw-r--r-- | fish_prompt.fish | 35 |
2 files changed, 315 insertions, 146 deletions
diff --git a/config.fish b/config.fish index b9e75a3..691cf03 100644 --- a/config.fish +++ b/config.fish @@ -1,183 +1,355 @@ -# Helper functions +# -*- mode: fish -*- + +########## Helper functions ########## + +# Wrapper around fish_add_path that verifies path existence function path-prepend - set -l p $argv[1] - if [ -d $p ] - and not contains $p $PATH - set -gx PATH $p $PATH - end + [ -d "$argv[1]" ]; and fish_add_path --prepend $argv[1] +end + +# Wrapper around fish_add_path that verifies path existence +function path-append + [ -d "$argv[1]" ]; and fish_add_path --append $argv[1] end +# Append given path to CDPATH function cdpath-append - set -l p $argv[1] - if [ -d $p ] - and not contains $p $CDPATH - set -gx CDPATH $CDPATH $p - end + set _path $argv[1] + if [ -d "$_path" ] + and not contains $_path $CDPATH + set -gx CDPATH $CDPATH $_path + end end +# Returns whether given command is in PATH function is-command - command -s $argv[1] > /dev/null + command -q $argv[1] end -function alias-if-in-path - set -l name $argv[1] - set -l values (string split ' ' $argv[2]) - set -l cmd $values[1] - if [ $cmd = 'sudo' ] - set cmd $values[2] - end - if is-command $cmd - alias $name "$values" - end +# Create an alias only if the aliased command is in PATH +function cond-alias + set name $argv[1] + set values (string split " " $argv[2]) + set cmd $values[1] + switch $cmd + case sudo cd cat exec + # Trim ( prefix from command + set cmd (string trim --left --chars "(" $values[2]) + end + if is-command $cmd + alias $name "$values" + end end -function ls-command - set -l ls_opts '--group-directories-first --color=auto' - switch (uname) - case Darwin FreeBSD - if is-command exa - echo "exa $ls_opts" - else if is-command gls - echo "gls $ls_opts" - else if is-command gnuls - echo "gnuls $ls_opts" - else - echo 'ls -G' - end - case '*' - echo "ls $ls_opts" - end -end +########## Environment ########## -function ll-command - if is-command exa - printf '%s -l\n' (ls-command) - else - printf '%s -lh\n' (ls-command) - end +# Locale +switch (uname) + case Darwin + set -gx LANG "en_US.UTF-8" + # iTerm may choose to set an invalid LC_CTYPE + # https://superuser.com/a/1400419 + set -gx LC_CTYPE "en_US.UTF-8" + # Norwegian time locale + set -gx LC_TIME "no_NO.UTF-8" + case Linux + set -gx LANG "en_US.UTF-8" + # Norwegian locale on Linux is named differently + set -gx LC_TIME "nb_NO.UTF-8" end -# Remove greeting -set fish_greeting - -# Prompt -set -g __fish_git_prompt_color_branch red -set -g fish_color_user green -set -g fish_color_host green -set -g fish_color_at green -set -g fish_color_cwd blue -set -g fish_color_command green -set -g fish_color_param grey -set -g fish_prompt_pwd_dir_length 0 - -# Set locale on Darwin -if [ (uname) = 'Darwin' ] - set -gx LANG 'en_US.UTF-8' - set -gx LC_CTYPE 'en_US.UTF-8' +# Set TERM +switch $TERM + case "xterm*" + set -gx TERM "xterm-256color" + case "screen*" "tmux*" + # OS may lack terminfo entry for tmux-256color + # https://github.com/tmux/tmux/issues/2262 + set -gx TERM "screen-256color" end -# Set terminal inside tmux -if set -q TMUX - set -gx TERM 'screen-256color' +# Homebrew +if [ -x /usr/local/bin/brew ] + eval $(/usr/local/bin/brew shellenv) +else if [ -x /opt/homebrew/bin/brew ] + eval $(/opt/homebrew/bin/brew shellenv) +end +if is-command brew + set -gx HOMEBREW_NO_ANALYTICS 1 + set -gx HOMEBREW_NO_AUTO_UPDATE 1 end # Set PATH -path-prepend /usr/local/sbin -path-prepend /usr/local/bin -path-prepend $HOME/Library/Python/3.6/bin -path-prepend $HOME/Library/Python/2.7/bin -path-prepend /usr/local/go/bin -path-prepend $HOME/.cargo/bin -path-prepend $HOME/.local/bin +path-prepend "/usr/local/sbin" +path-prepend "/usr/local/bin" +path-prepend "/Library/TeX/texbin" +path-prepend "/Applications/IntelliJ IDEA CE.app/Contents/plugins/maven/lib/maven3/bin" +path-prepend "$HOME/.local/bin" +path-prepend "$HOME/.cargo/bin" # Set CDPATH -cdpath-append . cdpath-append $HOME cdpath-append $HOME/p # Configure less -if is-command lesspipe - set -l lesspipe (command -s lesspipe) - set -gx LESSOPEN "|$lesspipe %s" -else if is-command lesspipe.sh - set -l lesspipe (command -s lesspipe.sh) - set -gx LESSOPEN "|$lesspipe %s" -end - if is-command less - set -gx LESS '-Ri' + set -gx LESS "-Ri" + set -gx PAGER "less" + # Add colors to man pages + set -gx LESS_TERMCAP_mb (printf "\e[1;32m") # Begins blinking. + set -gx LESS_TERMCAP_md (printf "\e[1;32m") # Begins bold. + set -gx LESS_TERMCAP_me (printf "\e[0m") # Ends mode. + set -gx LESS_TERMCAP_se (printf "\e[0m") # Ends standout-mode. + set -gx LESS_TERMCAP_so (printf "\e[1;31m") # Begins standout-mode. + set -gx LESS_TERMCAP_ue (printf "\e[0m") # Ends underline. + set -gx LESS_TERMCAP_us (printf "\e[4m") # Begins underline. end -# Add colors to man pages -set -gx LESS_TERMCAP_mb (printf '\e[01;31m') -set -gx LESS_TERMCAP_md (printf '\e[01;31m') -set -gx LESS_TERMCAP_me (printf '\e[0m') -set -gx LESS_TERMCAP_se (printf '\e[0m') -set -gx LESS_TERMCAP_so (printf '\e[00;47;30m') -set -gx LESS_TERMCAP_ue (printf '\e[0m') -set -gx LESS_TERMCAP_us (printf '\e[01;32m') - -# Set EDITOR to emacs or vim +# Set EDITOR, from most to least preferred if is-command emacsclient - set -gx EDITOR 'emacsclient -q' + set -gx EDITOR "emacsclient" else if is-command emacs - set -gx EDITOR 'emacs' + set -gx EDITOR "emacs" else if is-command mg - set -gx EDITOR 'mg' + set -gx EDITOR "mg" +else if is-command jmacs + set -gx EDITOR "jmacs" else if is-command vim - set -gx EDITOR 'vim' + set -gx EDITOR "vim" +else if is-command vi + set -gx EDITOR "vi" end # Remove mosh prefix from terminal title if is-command mosh - set -gx MOSH_TITLE_NOPREFIX '1' + set -gx MOSH_TITLE_NOPREFIX 1 +end + +# Use bfs as find command in fzf +if is-command fzf + and is-command bfs + set -gx FZF_DEFAULT_COMMAND bfs + set -gx FZF_CTRL_T_COMMAND $FZF_DEFAULT_COMMAND +end + +# Kill mosh-server if it has been inactive for a week +if is-command mosh-server + set -gx MOSH_SERVER_NETWORK_TMOUT 604800 end # GOPATH -if [ -d $HOME/go ] - set -gx GOPATH $HOME/go - path-prepend $GOPATH/bin - cdpath-append $GOPATH/src/github.com/mpolden +if [ -d "$HOME/go" ] + set -gx GOPATH $HOME/go + path-prepend $GOPATH/bin end # JAVA_HOME if [ -x /usr/libexec/java_home ] - set -l java_home (/usr/libexec/java_home 2> /dev/null) - if [ -n $java_home ] - set -gx JAVA_HOME $java_home - end + set -l java_home (/usr/libexec/java_home 2> /dev/null) + if [ -n "$java_home" ] + set -gx JAVA_HOME $java_home + end end # MAVEN_OPTS # Prevent Maven from running tasks in the foreground if is-command mvn - set -gx MAVEN_OPTS '-Djava.awt.headless=true' + set -gx MAVEN_OPTS "-Djava.awt.headless=true" +end + +########## Aliases ########## + +# Display ANSI art typically found .nfo files correctly +function nfoless + set pager $PAGER + if [ -z "$pager" ] + set pager less + end + iconv -f 437 -t utf-8 $argv | $pager +end + +# Show restic diff for the most recent snapshot. If offset is given, show the +# diff for the nth most recent snapshot instead +function restic-review + set offset $argv[1] + if [ -z "$offset" ] + set offset 0 + end + set matched (string match --regex "^[0-9]+" $offset) + if [ (count $argv) -gt 1 ] + or [ "$matched" != "$offset" ] + echo "usage: restic-review [OFFSET]" 1>&2 + return 1 + end + restic snapshots --group-by host --host (hostname -s) | \ + grep -Eo "^[a-f0-9]{8,}" | \ + tail -(math 2 + $offset) | \ + head -2 | \ + xargs -r restic diff +end + +# Fuzzy-finding wrapper for brew install, info and uninstall +function brew-fzf + switch $argv[1] + case info install uninstall + cat (brew formulae | psub) (brew casks | sed "s/^/--cask /" | psub) | fzf --multi | xargs -r brew "$argv[1]" + case "*" + echo "usage: brew-fzf [ info | install | uninstall ]" 1>&2 + return 1 + end +end + +# diff alias +function alias-diff + # Use colors in diff output when supported + if diff --color=auto /dev/null /dev/null 2> /dev/null + alias diff "diff --color=auto" + end +end + +alias-diff + +# ls alias +function alias-ls + set ls_opts "--group-directories-first --color=auto" + switch (uname) + case Darwin FreeBSD + if is-command gls + alias ls "gls $ls_opts" + alias ll "gls $ls_opts -lh" + else if is-command gnuls + alias ls "gnuls $ls_opts" + alias ll "gnuls $ls_opts -lh" + else + alias ls "ls -G" + alias ll "ls -Glh" + end + case "*" + alias ls "ls $ls_opts" + alias ll "ls $ls_opts -lh" + end +end + +alias-ls + +# Activate or deactivate a virtualenv in the directory venv +function venv + set venv $argv[1] + if [ -z "$venv" ] + set venv .venv + end + set venv (realpath $venv) + set activate "$venv/bin/activate" + if [ -n "$VIRTUAL_ENV" ] + echo "venv: deactivating $VIRTUAL_ENV" 1>&2 + deactivate + else if [ -f "$activate" ] + echo "venv: activating $venv" 1>&2 + source "$activate" + else + echo "venv: $activate not found" 1>&2 + return 1 + end +end + +# A shell variant of the locate-dominating-file function found in Emacs +function locate-dominating-file + if [ (count $argv) -lt 2 ] + echo "usage: locate-dominating-file START-PATH FILE" 1>&2 + return 1 + end + set file $argv[1] + set name $argv[2] + set dir $file + # If given file is indeed a file, we start in its directory + if not [ -d "$dir" ] + set dir (path dirname "$dir") + end + if not [ -d "$dir" ] + echo "locate-dominating-file: $dir is not a directory" 1>&2 + return 1 + end + set cur_dir $dir + while true + set cur_dir (realpath $cur_dir) + if [ -e "$cur_dir/$name" ] + echo "$cur_dir" + break + else if [ "$cur_dir" = "/" ] + echo "locate-dominating-file: $name not found in $dir or any of its parents" 1>&2 + return 1 + end + set cur_dir "$cur_dir/.." + end +end + +# Change directory to the nearest one containing the given file or directory +# +# Example: +# +# ~/project/some/deep/path$ cdn .git # or README.md, go.mod etc. +# ~/project$ +# +function cdn + cd (locate-dominating-file "$PWD" $argv[1]) +end + +cond-alias aptup "sudo apt update; and sudo apt upgrade" +cond-alias ec "emacsclient -nq" +cond-alias find bfs +cond-alias git-root "cd (git rev-parse --show-toplevel)" +cond-alias grep "grep --color=auto" +cond-alias mg "mg -n" +cond-alias ta 'tmux new-session -AD -s $LOGNAME' +cond-alias week "date +%V" +cond-alias reload "exec fish" +if is-command "apt-mark" + # This is the most precise method I've found for answering the question + # "which packages did I install explicitly?" + # + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=727799 + # https://stackoverflow.com/q/58309013/22831 + alias apt-leaves 'sudo grep -oP "Unpacking \K[^: ]+" /var/log/installer/syslog | sort -u | comm -13 /dev/stdin (apt-mark showmanual | sort | psub)' end -# Aliases -alias git-root 'cd (git rev-parse --show-toplevel)' -alias week 'date +%V' -alias ls (ls-command) -alias ll (ll-command) -alias-if-in-path grep 'grep --color=auto' -alias-if-in-path aptup 'sudo apt update; and sudo apt upgrade' -alias-if-in-path autossh 'autossh -M 0 -o "ServerAliveInterval 10"' -alias-if-in-path diff 'colordiff' -alias-if-in-path ec 'emacsclient -nq' -alias-if-in-path mg 'mg -n' + +########## Extensions ########## + +if status is-interactive + and source "$HOMEBREW_PREFIX/opt/fzf/shell/key-bindings.fish" 2> /dev/null + fzf_key_bindings +end + +########## Behavior ########## + +# Remove greeting +set fish_greeting + +# Prompt +set -g __fish_git_prompt_color_branch red +set -g fish_color_user green +set -g fish_color_host green +set -g fish_color_at green +set -g fish_color_cwd blue +set -g fish_color_command green +# Don't shorten working directory in prompt +set -g fish_prompt_pwd_dir_length 0 +# Make autosuggestion text slightly brighter +set -g fish_color_autosuggestion 8a8a8a # Print message if reboot is required -if status is-interactive > /dev/null - and [ -n "$TERM" ] - and [ -f /var/run/reboot-required ] - echo 'reboot required' +if status is-interactive + and [ -n "$TERM" ] + and [ -f /var/run/reboot-required ] + echo "reboot required" end # Local configuration -if [ -s $HOME/.config/fish/local.fish ] - source $HOME/.config/fish/local.fish -end +source $HOME/.config/fish/local.fish 2> /dev/null -# Clean up helper functions -functions -e path-prepend cdpath-append is-command alias-if-in-path ls-command \ - ll-command +# Clean up functions +if not is-command brew + functions -e brew-fzf +end +functions -e path-prepend path-append cdpath-append is-command cond-alias \ + alias-diff alias-ls diff --git a/fish_prompt.fish b/fish_prompt.fish index fde66b0..f415b4b 100644 --- a/fish_prompt.fish +++ b/fish_prompt.fish @@ -1,35 +1,32 @@ -function fish_prompt --description 'Write out the prompt' +function fish_prompt --description "Write out the prompt" + set last_status $status if not set -q __fish_prompt_hostname set -g __fish_prompt_hostname (hostname -s) end + set normal (set_color normal) set -q fish_color_at or set -U fish_color_at $normal - set -l normal (set_color normal) - set -l ssh_prefix - if set -q SSH_TTY + # Add user@host when connected through SSH or using toolbox + set ssh_prefix + if set -q SSH_CLIENT + or set -q SSH_TTY + or set -q SSH_CONNECTION + or set -q TOOLBOX_PATH set ssh_prefix (set_color $fish_color_user) $USER \ (set_color $fish_color_at) @ (set_color $fish_color_host) \ - $__fish_prompt_hostname $normal ':' + $__fish_prompt_hostname $normal ":" end - # Display fancy symbol on darwin + # Color prompt symbol based on exit status. Inspired by + # https://solovyov.net/blog/2020/useful-shell-prompt/ set __prompt_symbol '$' - if [ -z "$EMACS" -a (uname) = 'Darwin' ] - set -l burger (echo -ne '\xF0\x9F\x8D\x94') - set -l coffee (echo -ne '\xE2\x98\x95') - set -l beer (echo -ne '\xF0\x9F\x8D\xBA') - set -l hour (date +%-k) - if [ $hour -ge 8 -a $hour -lt 16 ] - set __prompt_symbol "$coffee " - else if [ $hour -ge 16 -a $hour -lt 19 ] - set __prompt_symbol "$burger " - else - set __prompt_symbol "$beer " - end + if [ $last_status -ne 0 ] + set __prompt_symbol "$(set_color yellow)\$$normal" end + # Print prompt echo -n -s $ssh_prefix (set_color $fish_color_cwd) (prompt_pwd) \ - $normal (__fish_git_prompt ' %s') $normal $__prompt_symbol ' ' + $normal (__fish_git_prompt " %s") $normal $__prompt_symbol " " end |