The fish shell
Published: January 31, 2015
I've been using zsh
with a few customizations for quite a while now and I can
honestly say that I would never go back to just using plain bash (although that
is not entirely true: I do my scripting in bash, since bash is the common
denominator amongst many *nix systems).
Some of the things that I liked about zsh
include better tab completion and
interactive syntax highlighting. I also configured my prompt to show the
current status of a git repository, if the current directory contains one. Some
of these customizations felt like a bunch of hacks, but they worked just fine.
Today I stumbled across the fish
shell, which, unlike zsh
, breaks backward
compatibility to bash, but advertises itself as a "smart and user-friendly
command line shell for OS X, Linux, and the rest of the family."
So, curious as I am, I installed it and played around with it. I really liked
my custom zsh
prompt, so one of the first things I tried to do was to
recreate it in fish
. Unlike in bash
or zsh
, the prompt is not set by a
P$1
or PROMPT
variable, but rather by executing a pair of functions called
fish_prompt
and fish_right_prompt
. Both of these functions lay in separate
files in the directory ~/.config/fish/functions
, and in case they are being
changed, the shell always executes the latest version. Neat!
One of the things that sold me on fish
was the nice and pain-free syntax used
for configuration and scripting. For example, look at this snippet from my
.zshrc
, where I configure my prompt:
spc_cnt=$(hostname | wc -m) let "spc_cnt-=1" spaces=$(printf ' %.0s' {1..$spc_cnt}) ZLE_RPROMPT_INDENT=0 autoload -U promptinit promptinit source ~/.git_prompt.zsh hostname="%{$fg[blue]%}%m%{$fg[red]%}%B|%b" return_indicator="%B%(?,%{$fg[green]%}✓%{$reset_color%},%{$fg[red]%}:(%{$reset_color%}%b" directory_indicator="%{$fg[yellow]%}%~" prompt_last="$spaces%{$fg[red]%}%B|%b%{$reset_color%}▸ " _newline=$'\n' PROMPT=$_newline$hostname$directory_indicator$_newline$prompt_last RPROMPT=$RPROMPT$return_indicator
A little chaotic, right? In contrast, here are my fish_prompt
and
fish_right_prompt
functions:
function fish_prompt --description 'Write out the prompt' set -l spc_cnt (math (hostname | wc -m) - 1) set_color blue printf "\n" printf (hostname) set_color red -o printf "|" set_color yellow printf (prompt_pwd_dennis); printf "\n" for x in (seq $spc_cnt); printf " "; end set_color red -o printf "|" set_color normal printf "▸ " end
function fish_right_prompt set -l last_status $status set_color normal printf '%s ' (__fish_git_prompt) if test $last_status -eq 0 set_color green printf "✓" else set_color red printf ":(" end end
Note that fish
has a built-in git
status prompt, so no more hacks to get
that functionality in zsh
!
The final thing that sold me on fish
was the great tab completion feature:
When I enter a command, fish
prints its suggestions in a light grey as I'm
typing in my command. Together with its equally great syntax highlighting,
fish
is just a pleasure to use!
The picture at the top of this post illustrates the tab completion and also
shows my prompt, together with my git status indicator. I will keep using
fish
as my everyday shell for now and I will blog about some more tricks that
I pick up along the way.
Best, Dennis