I’ve been trying fish
, however briefly, for a few years now. This time, I finally stuck with it. If you’re interested in seeing what the initial adjustment period is like, have a look at fish: the inital adjustment period.
Previously, I’d try fish
only to discover that it didn’t support changing the title of Terminal.app or that fish
sessions wouldn’t restore properly1. By fish
3.0.2, both of these problems were fixed and I was able to give fish
a fair try.
After a bit I ended up liking it. fish
bills itself as “the friendly interactive shell”. I’d describe fish
as “just a little bit nicer”.
You can browse the fish
site to get an idea of some of its feature set and what makes it better than other shells. This page lists some of the reasons why I like fish
more than bash
3.2.57, the version that ships with macOS 10.14:
Configuration goes in ~/.config/fish/
, making it easier to version-control
bash
configuration tends to be sprawled at the top level of one’s home directory. In order to properly version-control bash
dotfiles, one needs to either:
- put them in a version-controlled directory elsewhere and symlink to them from
~
- use a version-control system that doesn’t try to version-control everything in
~
, like src.
I like src
, but I can’t use it to sync changes between my desktop and laptop through a service like GitHub. ~/.config/fish/
, however, is easily synced with a git push
on one machine and a git pull
on the other.
No profile/rc split
bash
has both ~/.bashrc
and ~/.bash_profile
. I never really did understand when each gets loaded up. When I was first bitten by this split, I decided to write both such that they both sourced ~/.globalbashrc
and that was the end of it. Later on, as I moved to Macs mostly full-time and stopped bouncing between terminals both inside and outside the X Window system, I got less defensive with my bash
configuration and moved to sourcing ~/.bashrc
from my ~/.bash_profile
, although I couldn’t tell you why I did it this way and not the other way. At any rate, I have my $PS1
-prompt twiddling and alias setup in ~/.bashrc
and my $PATH
prepending in ~/.bash_profile
, although I couldn’t tell you why.
fish
, mercifully, is much simpler, or at least it’s easier to understand where to put things.
- Settings that
fish
likes setting itself (colors, etc.) go in~/.config/fish/fish_variables
. (The convenience of universal variables is nice, but readingfish_variables
with its\x1e
and similar escapes is a bit of a chore for long variables.) ~/.config/fish/functions/
for, well, all functions. One file per function. (fish uses functions for the sorts of things one would use an alias for inbash
.)~/.config/fish/config.fish
for everything else, including building up$PATH
and$EXA_COLORS
over multiple lines apiece.
?
doesn’t glob
This is a small thing, but dagnabbit, I like it.
I use youtube-dl a fair amount. If I’m downloading a URL like https://www.youtube.com/watch?v=dQw4w9WgXcQ
, I need to quote it with single quotes in bash
. I don’t need to bother typing the quotes in fish
if I’ve done set -U fish_features stderr-nocaret qmark-noglob
first.
Why also stderr-nocaret
? It disables an old annoyance that I ran into. ^
isn’t anything special in bash
, but it is in fish
. git diff HEAD^ HEAD
works just fine in bash
, but you’ll want to enable stderr-nocaret
in fish
to keep git and regex annoyances to a minimum.
Tab-completable makefile targets
I use simple makefiles in most of my projects. Not only do makefiles reduce the amount of typing you have to do, but they’re a useful memory aid when you return to a project after a spell and wonder “how do I make it go, again?”. Previously, in order to view makefile targets, I’d have to cat
the file to see what targets were in the makefile. With fish
, though, all I need to do is type make
, a space, and then hit the tab-key twice.
More-accessible history
This is the feature that I end up using the most, it seems.
fish
history autocompletes. Press → or C-f to complete the current suggestion. It’s a bit weird to see your old Git commit messages autocomplete when you type git commit -am
, but seeing cd Projects/Go/src
after just typing cd
gets handy. I wouldn’t bother searching through my history and typing !234
for something like that.
If you want to keep a few commands out of your history, fish -P
starts fish
in private mode. I’ve used this for a screencast or two.
If these features sound neat, head on over to the fish website to find out more. If you’re wondering whether switching is a pain (it was for me, if only for a few days), have a look at my page on the initial adjustment period.
-
Frequently, I have four different Terminal windows open to four different paths. Back when
fish
didn’t support session restoration, each terminal would get reset to my home directory instead of wherever its current working directory was before I quit Terminal. This was more than enough to switch back tobash
. ↩︎