Serg Hospodarets Blog

Serg Hospodarets blog

Fish Shell- the missing config Serg Hospodarets Blog

After a long time using usual the Mac terminal I came to understanding that more advanced tool is needed for many common aspects of daily work.

For example: some commands autosuggestions which will remember your previous commands and be smart enough to repeat them depending on a situation. Another requirement from a UI-lover part of my soul- good syntax highlighting.

The best, if such tool wouldn’t require much time for setup and configuration to start working out of the box.

After some research I settled on 2 options: fish shell and Z shell (zsh). Either are worth and have their advantages/disadvantages.

I decided to try Fish Shell as one of my biggest requirements installation without need of long configuration. It’s really something Fish was designed for.

If you are interested in Z shell starting guide and plugins- you can watch nice manuals from Wes Bos.

Looking for the best terminal option

As I use Mac, there is not bad terminal inside OS X.

But sometimes you might need even more features:

  • activate and focus terminal pressing HotKey anywhere,
  • showing images right in the terminal (the best- together with animated GIFs),
  • split panels ability
  • flexible solution to have tons of setting in case you want to setup it exactly as you want.

There are a couple options but only one of them is good IMO- ITerm.

So you can just download/install it and use ITerm instead of the terminal.

Fish installation and first impressions

Just download and install Fish Shell from the official site: http://fishshell.com/

After that start Fish from your terminal running: fish

Try playing with autosuggestions and tabs- hope you’ll like it.

If you want to change your default terminal to Fish, you have to add Fish to valid login shells. For that to the /etc/shells file add the afterward line (requires administrative rights)

/usr/local/bin/fish

And then make Fish your default shell with chsh:

chsh -s /usr/local/bin/fish

Only one problem I noticed after doing that- my environment variables and aliases from ~/.bash_profile were not imported. Ofc. you are free to declare Fish-specific variables/aliases but it’s not something I would like to do, especially if one day I’ll switch to another shell or back to Bash.

After short research I just found an easy way to reuse them.

The missing config to reuse Bash variables and aliases in Fish

To reuse Bash vars and aliases we would just parse ~/.bash_profile and reapply them for Fish. For that add the following scripts to the Fish config at ~/.config/fish/config.fish:

# REUSE ALIASES FROM ~/.bash_profile
egrep "^alias " ~/.bash_profile | while read e
        set var (echo $e | sed -E "s/^alias ([A-Za-z0-9_-]+)=(.*)\$/\1/")
        set value (echo $e | sed -E "s/^alias ([A-Za-z0-9_-]+)=(.*)\$/\2/")

        # remove surrounding quotes if existing
        set value (echo $value | sed -E "s/^\"(.*)\"\$/\1/")

    # evaluate variables. we can use eval because we most likely just used "$var"
        set value (eval echo $value)

    # set an alias
    alias $var="$value"
end

# REUSE ENVIRONMENT VARIABLES FROM ~/.bash_profile
egrep "^export " ~/.bash_profile | while read e
    set var (echo $e | sed -E "s/^export ([A-Z0-9_]+)=(.*)\$/\1/")
    set value (echo $e | sed -E "s/^export ([A-Z0-9_]+)=(.*)\$/\2/")

    # remove surrounding quotes if existing
    set value (echo $value | sed -E "s/^\"(.*)\"\$/\1/")

    if test $var = "PATH"
        # replace ":" by spaces. this is how PATH looks for Fish
        set value (echo $value | sed -E "s/:/ /g")

        # use eval because we need to expand the value
        eval set -xg $var $value

        continue
    end

    # evaluate variables. we can use eval because we most likely just used "$var"
    set value (eval echo $value)

    #echo "set -xg '$var' '$value' (via '$e')"

    switch $value
            case '`*`';
            # executable
            set NO_QUOTES (echo $value | sed -E "s/^\`(.*)\`\$/\1/")
            set -x $var (eval $NO_QUOTES)
        case '*'
            # default
            set -xg $var $value
        end
end

After that open a new tab and enjoy your Bash stuff working in Fish:

alt

The script idea was taken from the SuperUser discussion , improved and added with aliases import.

Other additions to the config

NVM (Node Version Manager) doesn’t work in Fish out of the box

By default NMV (super handy tool to switch Node.js version on the fly) doesn’t work. But it’s easy to fix using NVM Fish wrapper.

For that in the terminal run:

cd ~/.config/fish

### copy the project files
git clone git://github.com/passcod/nvm-fish-wrapper.git nvm-wrapper

and edit your Fish config file:

vim ~/.config/fish/config.fish

adding nvm.fish there:

source ~/.config/fish/nvm-wrapper/nvm.fish

Open a new tab and try running nvm:

nvm in fish

Repeat previous command and last command option are missed in Fish

If you a big fun of usage sudo !! when previous command requires administrative rights or !$ to repeat the last command option you’ll notice they have to be added to Fish.

Fortunately the community already created a special page for this- Bash Refugees

To add them back just create/edit the Fish user key binding:

vim ~/.config/fish/functions/fish_user_key_bindings.fish

and add the following:

function bind_bang
  switch (commandline -t)
  case "!"
    commandline -t $history[1]; commandline -f repaint
  case "*"
    commandline -i !
  end
end

function bind_dollar
  switch (commandline -t)
  case "!"
    commandline -t ""
    commandline -f history-token-search-backward
  case "*"
    commandline -i '$'
  end
end

function fish_user_key_bindings
  bind ! bind_bang
  bind '$' bind_dollar
end

Fish Greeting

The default Fish intro is quite annoying IMO:

Welcome to fish, the friendly interactive shell

Type help for instructions on how to use fish

If you wish to remove it just add:

set fish_greeting ""

to your ~/.config/fish/config.fish.

The prompt

fish comes with a default prompt that shows your username, hostname, and working directory.

If you’d like to set it to be short, edit the ~/.config/fish/functions/fish_prompt.fish file, adding the following:

function fish_prompt
    set_color $fish_color_cwd
    echo -n (prompt_pwd)
    set_color normal
    echo -n '>'
end

And the result will be:

alt

Сonclusions

After that I started using Fish without even noticing I fully switched to it.

There might be some additional problems/disadvantages for you but for me Fish exactly solves problems it was supposed to and so far I’m happy with it.

Useful links

Provide your code in <pre><code>...</code></pre> tags in comments