Fish shell

Date: 2019/10/21 (initial publish), 2021/07/13 (last update)

Source: en/note-00008.md

Previous Post Top Next Post

TOC

NOTE (2021-01-07):

I gave up using fish early in 2000. I now stick to:

Original note:

Fish shell looks interesting to me since it makes handling of space in the filename a lot simpler and have simple but powerful string manipulation with PCRE2.

Let me make a simple deployment memo for Debian.

Set up Fish shell for GUI consoles

Official way to set the shell

Although chsh is the official way to switch the system default shell recorded in /etc/passwd, this is not always the robust approach to switch shell used in GUI consoles to the non-POSIX shells such as Csh and Fish under some Linux GUI environment. This is because some GUI initialization codes assume the system default shell to be a POSIX shell.

(For GNOME environment with “GNOME terminal”, it seems chsh works. But the started fish shell has $SHLVL to be 2 and $SHELL to be /bin/bash which are a bit awkward. KDE seems to have problem.)

Robust way to set the shell

The robust way to start Fish shell is to start it from modern terminal emulator programs such as “GNOME terminal”, “Konsole”, “xfce4-terminal”, and “MATE Terminal”. For them, there is a way to run a custom command as your shell from the menu. So set this custom command to /usr/bin/fish. With this approach, you can select the started shell from the menu.

Workaround to set the shell

If you can’t easily find a way to set up the custom command for other situations such as the “xterm”, “rxvt”, “LXterminal”, and “Qterminal”, one workaround is to select Bash as the system default shell and to place the following at the first line of your ~/.bashrc to start Fish:

exec /usr/bin/fish

When you really need to start Bash, you can comment out this line to regain the normal Bash behavior.

GUI setup of Fish

Executing fish_config on the Fish shell command prompt starts browser to set up Fish. This sets up 2 files:

Here, $XDG_CONFIG_HOME is usually ~/.config.

Initializing setup for Fish

User initialization setup for Fish is at $XDG_CONFIG_HOME/fish/config.fish which works like ~/.bashrc and ~/.zshrc.

I will list code snippets used in my ~/.config/fish/config.fish as below.

SHELL environment variable

Although Bash and the original Ksh set the $SHELL environment variable, not all shell programs set it. Fish shell is no exception. Some programs such as mc (Midnight Commander), screen, and tmux rely on the $SHELL environment variable to override the shell setting of of /etc/passwd updated by chsh.

Set the $SHELL environment variable for Fish:

set -x SHELL /usr/bin/fish

Here, set -x is used to export the environment variable.

Other environment variables

The next step is to migrate your old settings in ~/.bashrc.

# Always override SHELL=/bin/bash and make mc/screen/tmux happy
set -x SHELL /usr/bin/fish

# Exported environment variables
set -x EDITOR vim
set -x VISUAL vim
set -x BROWSER firefox
set -x MKISOFS xorrisofs
# devscripts related
set -x DEBEMAIL osamu@debian.org
set -x DEBFULLNAME Osamu\ Aoki

# set CDPATH
set -x CDPATH . /usr/share/doc ~ ~/pub/salsa ~/pub/github ~/pub/tmp

# set PATH of normal users to include "sbin"
set -x PATH $PATH /usr/sbin /sbin

# python distutils
if test -d ~/.local/bin
  set -x PATH ~/.local/bin $PATH
end

# user's private bin
if test -d ~/bin
  set -x PATH ~/bin $PATH
end

Initializing Builtin commands

The next step is to initialize Fish sell using builtin commands.

# User Private Groups: http://wiki.debian.org/UserPrivateGroups
umask 002
# make core file
ulimit -c unlimited

Here, I skipped fish_vi_key_bindings since web based configuration already set it up.

Configuring mc

Let’s make mc (Midnight Commander) to change directory upon exit by translating /usr/lib/mc/mc.sh to create an auto-loading function $XDG_CONFIG_HOME/fish/functions/mc.fish:

# Equivalent of /usr/lib/mc/mc.sh
function mc --description Midnight\ Commander\ which\ changes\ directory\ upon\ exit.
  set -l SHELL_PID %self
  set -l MC_USER (id -un)
  set -l MC_PWD_FILE
  if set -q TMPDIR
    set MC_PWD_FILE "$TMPDIR/mc-$MC_USER/mc.pwd.$SHELL_PID"
  else
    set MC_PWD_FILE "/tmp/mc-$MC_USER/mc.pwd.$SHELL_PID"
  end
  /usr/bin/mc -P $MC_PWD_FILE $argv
  set -l MC_PWD (cat $MC_PWD_FILE)
  if test -r $MC_PWD_FILE
    if test -n $MC_PWD ; and test -d $MC_PWD
      cd $MC_PWD
    end
    rm -f $MC_PWD_FILE
  end
end

Please note:

Configuring fzf

Let’s make fzf work well with Fish shell. The fzf package on Debian comes with a glue code in /usr/share/doc/fzf/examples but there is a better solution which uses auto-loading:

This requires to use package manager fisher.

FIXME fisher dosen’t work right (2019-12)

TODO

Configuring less

TODO

# make less more friendly for non-text input files, see lesspipe(1)
#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
Previous Post Top Next Post