ZSH was my default shell for many years. I have modified and moved .zshrc
across many different distributions of Linux. Recently I started working on a MacBook Pro, which has ZSH as the default shell. Using it for few months now, I noticed a few things about my ZSH configuration:
- The startup of the new shell had minor delays before it could be used. These delays weren't huge, but I started noticing it more and more on MacOS. We tend to interact faster with systems that gives us faster feedbacks.
- My
.zshrc
configuration had some plugins and configurations fromoh-my-zsh
that Fish shell mostly provides out-of-the-box.
With this in mind, I wanted to know how fast can I migrate to Fish shell while converting my current .zshrc
.
Fish Shell 🐠
Getting ready
My .zshrc
configuration looks like this:
# ---- ZSH ---- #
export ADOTDIR="$HOME/.antigen"
# Source antigen zsh plugin manager
source $HOME/.antigenrc
antigen init
# Autosuggestion color highlight
export ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#F2F0F6,underline"
export ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE=30
# History settings.
export HISTSIZE=1000000
export HISTCONTROL='ignoreboth'
export HISTORY_IGNORE="(clear|history)"
SAVEHIST=$HISTSIZE
# Add wisely, as too many plugins slow down shell startup.
plugins=(copyfile
extract
git-extras
git-flow-avh
zsh-autosuggestions
zsh-completions
zsh-syntax-highlighting
colored-man-pages
z)
# ------------- #
# ---- User Configuration ---- #
## Nix specific
export NIX_PATH=darwin-config=$HOME/.nixpkgs/darwin-configuration.nix:$HOME/.nix-defexpr/channels${NIX_PATH:+:}$NIX_PATH
source $HOME/.nix-profile/etc/profile.d/hm-session-vars.sh
source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
eval "$(starship init zsh)"
# Leave less preview on screen when quit
export LESS="-RX"
export EDITOR='nvim'
export LESS_TERMCAP_md="${yellow}"
# ---------------------------- #
# ---- Alias ---- #
alias vim="nvim"
alias l="exa --long --header --all"
alias ls="exa --long --header"
alias tree="exa --tree --level=2"
alias cat="bat"
alias ping="ping -c 3"
# Add verbose output on these commands
alias rm="rm -v"
alias mkdir="mkdir -v"
alias mv="mv -v"
alias cp="cp -v"
# --------------- #
#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!
export SDKMAN_DIR="$HOME/.sdkman"
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
Setup
Install Fish and Fisher (plugin manager for Fish):
brew install fish fisher
Fish configurations are located at ~/.config/fish
. Now we can activate fish shell using fish
command to get started.
Alias
To convert aliases, simply paste them and use funcsave
to save them at ~/.config/fish/functions
:
alias cp="cp -v"
alias mv="mv -v"
...
funcsave cp mv ...
ENV variables
Use Universal Variables:
set -Ux EDITOR "nvim"
...
Plugins
Use Fisher to install several helpful plugins.:
fisher install jethrokuan/z # Jump around the folders
fisher install decors/fish-colored-man
fisher install oh-my-fish/plugin-peco # Ctrl + R for searching history
fisher install oh-my-fish/plugin-extract
Note that some of Fish plugins are enabled by default and there is no need to set the up like in ZSH.
I also found below plugins useful while converting my .zshrc
(though you may won't need them)
fisher install reitzig/sdkman-for-fish
fisher install lilyball/nix-env.fish
fisher install jorgebucaran/nvm.fish
Prompt
I use Starship which is "Cross-Shell Prompt" so my configurations for Starship are automatically applied. To enable it, just use:
echo "starship init fish | source" >> $HOME/.config/fish/config.fish
Results
Benchmarks
Using hyperfine at first run, I've noticed Fish is faster than ZSH to some extent:
I got curious why both shells take so much time to start. Profiling both shells, I figured out that both of them have performance degradation due to SDKMan enabled (manages multiple Java Distributions similar to NVM).
Once SDKMan is removed for both shells, I re-ran benchmarks again:
With both shells being almost similar in my setup, Fish shell ran 3 times faster than ZSH.
Benefits
I find my shell configuration more organized now using Fish. Syntax of Fish scripts feel lot more readable compared to ZSH/Bash scripts. Other noticeable features that I found useful:
- Auto suggest command completions (
fish_update_completions
) -
CTRL
+R
with Peco for searching history easily - Great plugins
- Faster compared to my ZSH
Gotchas
Although converting configurations was extremly fast, I spent a lot of time on following:
- I keep backups of ZSH history dating back several years. There is a tool to convert ZSH history to Fish, but it didn't kept timestamp of execution. Also, some of multiline commands
(such as
curl
) brokefish_history
file. The tool works, but may have to manually correct errors. - Poetry completions produce errors. I though it was error something due to Fish, but found out later that this will be fixed.
- Some of the builds scripts (Makefiles, builds tasks...) exported certain ENV variables using
export
so running it with Fish produced errors.
Conclusion
In this state, I have migrated from ZSH to Fish really fast and set it as default shell, keeping the same configurations. Without gotchas that I ran in to, time of converting was less than 10 minutes. I find my shell much faster now, using new plugins and some other that Fish provides by default.
At the end, I suggest you try it. If it doesn't work, you can always go back to your previous configuration.
Top comments (0)