I am one of those people who immediately opens a terminal window after my computer boots up. It's not out of necessity at this point, but the habit is there. I spent most of my career learning its magical incantations, and I find navigating through my daily tasks on the terminal makes for a more enjoyable day at work. That all said, it's nice to try something new once in a while.
I recently let go of the default command line interpreter, Bash, in favor of fish, which proudly markets itself as "a command line shell for the '90s." Here's why I switched.
![fish shell website fish shell website](https://opensource.com/sites/default/files/uploads/fish_0.png)
I found that .bashrc is not enough
A little over a year ago I decided to stop abstracting away my operating systems and start to learn it from the ground up. I recently switched from Mac to Linux, which gave me a reason to look into porting my dotfiles to the new environment. It was refreshing; I found a ton of confusing shortcuts and duplication and paired it down to something that ports between operating systems well. Here are a few favorites:
## Nicer shell experience
export GREP_OPTIONS="--color=auto"; # make grep colorful
export LSCOLORS=gxfxbEaEBxxEhEhBaDaCaD; # make ls more colorful as well
export HISTSIZE=32768; # Larger bash history (allow 32³ entries; default is 500)
export HISTFILESIZE=$HISTSIZE;
export HISTCONTROL=ignoredups; # Remove duplicates from history. I use `git status` a lot.
export HISTIGNORE="ls:cd:cd -:pwd:exit:date:* --help"; # Make some commands not show up in history
export LANG="en_US.UTF-8"; # Language formatting is still important
export LC_ALL="en_US.UTF-8"; # byte-wise sorting and force language for those pesky apps
export MANPAGER="less -X"; # Less is more
export GPG_TTY=$(tty); # for gpg key management
I've been on a journey to demystify the magic of my environment, and it is starting to make more sense.
Customization breaks my .bashrc
It's at this point of clarity that I got stuck again. I want some modern conventions in my terminal, especially auto-suggestions, syntax highlighting, and colorization of command outputs without too many dependencies, and I'd like that configuration to be independent of whatever command line interpreter I'm running. (iTerm2 is great on a Mac, but I don't want to track its cryptic configuration file in my dotfiles.) So what am I to do?
The first time I went after an answer, I solved it one step at a time:
- First, I customized my ~/.inputrc file to allow for forward and backward search.
- Then, I replaced cat with the prettified output of ccat and aliased cat to ccat in my .bashrc. This later eventually broke writing to stdout in some cases, so I stopped using it.
- Ultimately, I used Bash-it, which is a powerful plugin system for customizing Bash.
After peeling back the pieces one-by-one, I felt I understood a bit more about how my system ran. The hoops I felt like I had to jump through to get the modern experience I sought led me back to the standards that brought me to this point. I felt like I was a prisoner of history until I decided to throw it all away and try something totally different.
Easy defaults and customization with fish shell
Fish shell is a modern command-line interface with auto-suggestions, tab completion, and syntax highlighting (among other features). I especially like how from the first time you give it a try by typing fish, you get a beautiful experience:
![An example of the fish shell with Solarized Light theme An example of the fish shell with Solarized Light theme](https://opensource.com/sites/default/files/uploads/fish-shell-example-opensourcedotcom.png)
In the first line, the command is blue because pwd is a valid command. On the second line, it is red because pdw is not a valid command. I hit Enter to show that it's true, but I could have quickly corrected the error and moved on with my day. In the third command, I want to change directory (cd) into my Development folder, and fish automatically asks whether I want to hop into my dotfiles, as I did the last time. When I hit Tab twice, it shows other options in the same directory, just like I'd expect.
If I want to customize my fish shell experience, I don't need to install any additional library or framework to do so. Fish ships with the fish_config command, which launches a graphical user interface (GUI) where you can choose different colors and prompt configurations.
![fish shell's colors fish shell's colors](https://opensource.com/sites/default/files/uploads/fish-colors.png)
What's more impressive is you can review all available functions, variables, bindings, and more from the GUI as well:
![fish functions fish functions](https://opensource.com/sites/default/files/uploads/functions.png)
If you tune your configuration, all customizations are stored in the same place: ~/.config/fish. The screenshot above shows that I made a custom function that allows me to easily activate a Python environment using pyenv. Check out the tutorial on fish functions for more.
Be warned: fish is not like Bash
When trying out other shells, I found there were always a few differences I needed to tune, but they felt familiar overall. That is not the case with fish. Function definition, aliasing, and variables all work a little differently. There are helpful strategies for converting .bashrc and .bash_profile files into fish configuration, but it's more than I will cover in this article. So, while I've grown to love fish, I recommend taking the interactive tutorial for a spin to see if you like it.
Give fish a try for a beautiful default shell
I enjoy starting my day by opening up the terminal, and I enjoy it even more since switching to the fish shell. It's allowed me to shift away from worrying about what's in Bash to focusing on what code I plan to write. If you're looking to move away from tinkering with your terminal and focus more on code, give it a try. Use chsh to set it as your default shell, and let me know how it goes in the comments.
8 Comments