A good[ish] website
Web development blog, loads of UI and JavaScript topics
This is fish shell, the shell for the future, the shell to match your modern home terminal’s needs and requirements.
I taught myself to use fish a while ago, and now, I’m going to write a tutorial about it, and here are some of its quirks and features.
Fish is a shell, like bash, but different. Some of the selling points include, but are not limited to:
$ brew install fish
See where your fish is installed:
$ which fish
/usr/local/bin/fish
Now append that to your shells file to make it available:
$ echo "/usr/local/bin/fish" >> /etc/shells
Now you can just do:
$ fish
And you’re using fish. Go back to bash if you like:
$ exit
Check your fish version:
$ fish --version
fish, version 3.1.0
Check if there’s a new version:
$ brew update
$ brew outdated
brew update
will update the homebrew package registry, and brew outdated
will list out-of-date homebrew packages.
Then just upgrade fish:
$ brew upgrade fish
Reload your terminal window and confirm the version:
$ fish --version
fish, version 3.1.2
You probably want to make it the default shell, issue the "change shell" command:
$ chsh -s /usr/local/bin/fish
Now restart or refresh your terminal and it should load to Fish.
But, if you still see your old bash and you’re using iTerm2, you might have defined the shell in the iTerm2 settings (like I had), just change the setting to "Login shell":
$ chsh -s /usr/local/bin/fish
again.Now iTerm should pick up fish when it restarts.
Run:
$ fish_config
That will open a web-based GUI where you can select a color theme and configure the look of the shell. When you’re done, come back to the shell and hit enter to exit the config mode.
An important directory for all fish users is ~/.config/fish
. All the config lives down there.
The file ~/.config/fish/config.fish
is equivalent to to .bash_profile
.
From there you can export your environmental variables, for example. fish has the --export
flag that you can use:
# config.fish
set --export AUTH_TOKEN blahBlah
The bash way of exporting variables seems to work, too:
export AUTH_TOKEN=blahBlah
Fisher makes it easy to install utilities. All you need to do is to add it to your functions directory:
$ curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
Syntax for adding packages with fisher:
┌── GitHub path to the repo
┌─────┴────┐
fisher add jethrokuan/z
That would install z
from github.com/jethrokuan/z.
Listing installed packages:
$ fisher ls
When you install packages, fisher writes them into ~/.config/fish/fishfile
. You can then subject this file to version control so you can keep your fish packages in sync between machines.
Fish is not POSIX compatible, so bash doesn’t work out of the box. But you can always do:
$ bash
That opens a bash shell, then $ exit
to get back.
But if you pass it the -c
option, bash will read from a string and you can stay in the current shell:
$ bash -c someBashCommand
Check man bash
for more.
In fish, you can of course run scripts written in any language you imagine if the shebang is correct (#!/bin/bash
). But some scripts modify the shell environment, and need to be sourced. This is what fish can’t do, but bass was designed to do just that. It’s a simple python wrapper that calls scripts in bash and passes in and out the needed environmental variables.
Install it with fisher:
$ fisher add edc/bass
For example, you can make nvm (Node Version Manager) work in fish:
function nvm
bass source (brew --prefix nvm)/nvm.sh ';' nvm $argv
end
Add that function to ~/.config/fish/functions
and call nvm normally.
This bridges us up to the nvm options in fish.
We all love nvm, but nvm doesn’t work right out the box in fish. But it’s not hard to get it running.
Simply wrap nvm
with bass
, as shown above.
fish-nvm is an nvm written in pure fish, no shenanigans. It has worked great for me. Install it with fisher:
$ fisher add jorgebucaran/fish-nvm
If you just want something easy that works, you can stop reading now.
fast-nvm-fish is a minimal script that aims to make your shell load-up really fast even when you have multiple node version installed. It doesn’t support aliases tho.
Bash has aliases and function. Fish simplifies this by only having functions. They’re stored in ~/.config/fish/functions
.
Few simple examples to showcase how the functions work:
# ~/.config/fish/functions/ls.fish
function ls
command ls --color=auto $argv
end
Get the current week number:
# ~/.config/fish/functions/week.fish
function week --description "Gets the current week number"
date +%V
end
Really handy function to nuke all merged git branches:
# ~/.config/fish/functions/git_delete_merged.fish
function git_delete_merged --description='Deletes merged branches'
git branch --merged | grep -v '\*' | xargs -n 1 git branch -d
end
You simply call the function by its name to execute it:
$ git_delete_merged
About that --description
flag, it supposed to work so that you can see the description next to the function name when you tab complete. But I just can’t get it working. There used to be a bug rendering it useless, but it’s been fixed in the v3.0 of fish. Nonetheless, it doesn’t work for me.
Fish function to reload shell on Mac:
function reload --description 'Reloads shell (i.e. invoke as a login shell)'
exec $SHELL -l
end
You get the idea. Read briefly about functions from the official fish documentation, or more thoroughly in the commands documentation.
Here’s some more fish resources:
Comments would go here, but the commenting system isn’t ready yet, sorry.