aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2024-01-04 13:14:24 +0100
committerMartin Polden <mpolden@mpolden.no>2024-01-16 10:26:59 +0100
commit8cf4c07b6ef56cf913e454de2bfa9686520e29dd (patch)
tree97d6b5f2b94b8fee6a29b118b4324b6b4ec34daf
parent7a5ed8ea751110afe551d87aaf15582afe5c54c2 (diff)
fish: port current zsh config
-rw-r--r--config.fish426
-rw-r--r--fish_prompt.fish35
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