<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dinko Pehar</title>
    <description>The latest articles on Forem by Dinko Pehar (@dinkopehar).</description>
    <link>https://forem.com/dinkopehar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F563022%2Fa356642f-9a97-4c60-a303-dc4bbfede440.jpg</url>
      <title>Forem: Dinko Pehar</title>
      <link>https://forem.com/dinkopehar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dinkopehar"/>
    <language>en</language>
    <item>
      <title>From ZSH to Fish</title>
      <dc:creator>Dinko Pehar</dc:creator>
      <pubDate>Mon, 26 Sep 2022 16:50:46 +0000</pubDate>
      <link>https://forem.com/dinkopehar/from-zsh-to-fish-233o</link>
      <guid>https://forem.com/dinkopehar/from-zsh-to-fish-233o</guid>
      <description>&lt;p&gt;ZSH was my default shell for many years. I have modified and moved &lt;code&gt;.zshrc&lt;/code&gt; 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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;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 &lt;a href="https://bootcamp.uxdesign.cc/importance-of-doherty-threshold-ebe65f0b9fab" rel="noopener noreferrer"&gt;faster feedbacks&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;My &lt;code&gt;.zshrc&lt;/code&gt; configuration had some plugins and configurations from &lt;code&gt;oh-my-zsh&lt;/code&gt; that Fish shell mostly provides out-of-the-box.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With this in mind, I wanted to know how fast can I migrate to Fish shell while converting my current &lt;code&gt;.zshrc&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fish Shell 🐠
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Getting ready
&lt;/h3&gt;

&lt;p&gt;My &lt;code&gt;.zshrc&lt;/code&gt; configuration looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ---- ZSH ---- #&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ADOTDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.antigen"&lt;/span&gt;
&lt;span class="c"&gt;# Source antigen zsh plugin manager&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.antigenrc
antigen init
&lt;span class="c"&gt;# Autosuggestion color highlight&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fg=#F2F0F6,underline"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ZSH_AUTOSUGGEST_BUFFER_MAX_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;30
&lt;span class="c"&gt;# History settings.&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HISTSIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000000
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HISTCONTROL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'ignoreboth'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HISTORY_IGNORE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"(clear|history)"&lt;/span&gt;
&lt;span class="nv"&gt;SAVEHIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HISTSIZE&lt;/span&gt;
&lt;span class="c"&gt;# Add wisely, as too many plugins slow down shell startup.&lt;/span&gt;
&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;copyfile
         extract
         git-extras 
         git-flow-avh 
         zsh-autosuggestions 
         zsh-completions
         zsh-syntax-highlighting 
         colored-man-pages
         z&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# ------------- #&lt;/span&gt;

&lt;span class="c"&gt;# ---- User Configuration ---- #&lt;/span&gt;
&lt;span class="c"&gt;## Nix specific&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NIX_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;darwin-config&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.nixpkgs/darwin-configuration.nix:&lt;span class="nv"&gt;$HOME&lt;/span&gt;/.nix-defexpr/channels&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NIX_PATH&lt;/span&gt;:+:&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;$NIX_PATH&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.nix-profile/etc/profile.d/hm-session-vars.sh
&lt;span class="nb"&gt;source&lt;/span&gt; /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh

&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;starship init zsh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# Leave less preview on screen when quit&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"-RX"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;EDITOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'nvim'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;LESS_TERMCAP_md&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;yellow&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c"&gt;# ---------------------------- #&lt;/span&gt;


&lt;span class="c"&gt;# ---- Alias ---- #&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;vim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"nvim"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"exa --long --header --all"&lt;/span&gt;
&lt;span class="nb"&gt;alias ls&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"exa --long --header"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"exa --tree --level=2"&lt;/span&gt;
&lt;span class="nb"&gt;alias cat&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bat"&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;ping&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ping -c 3"&lt;/span&gt;
&lt;span class="c"&gt;# Add verbose output on these commands&lt;/span&gt;
&lt;span class="nb"&gt;alias rm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"rm -v"&lt;/span&gt;
&lt;span class="nb"&gt;alias mkdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mkdir -v"&lt;/span&gt;
&lt;span class="nb"&gt;alias mv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mv -v"&lt;/span&gt;
&lt;span class="nb"&gt;alias cp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cp -v"&lt;/span&gt;
&lt;span class="c"&gt;# --------------- #&lt;/span&gt;

&lt;span class="c"&gt;#THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!!&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SDKMAN_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sdkman"&lt;/span&gt;
&lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sdkman/bin/sdkman-init.sh"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.sdkman/bin/sdkman-init.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Install Fish and Fisher (&lt;em&gt;plugin manager for Fish&lt;/em&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;fish fisher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fish configurations are located at &lt;code&gt;~/.config/fish&lt;/code&gt;. Now we can activate fish shell using &lt;code&gt;fish&lt;/code&gt; command to get started.&lt;/p&gt;

&lt;h4&gt;
  
  
  Alias
&lt;/h4&gt;

&lt;p&gt;To convert aliases, simply paste them and use &lt;code&gt;funcsave&lt;/code&gt; to save them at &lt;code&gt;~/.config/fish/functions&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias cp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cp -v"&lt;/span&gt;
&lt;span class="nb"&gt;alias mv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mv -v"&lt;/span&gt;
...
funcsave &lt;span class="nb"&gt;cp mv&lt;/span&gt; ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ENV variables
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://stackoverflow.com/a/30187924/9871463" rel="noopener noreferrer"&gt;Universal Variables&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-Ux&lt;/span&gt; EDITOR &lt;span class="s2"&gt;"nvim"&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;Use Fisher to install several helpful plugins.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fisher &lt;span class="nb"&gt;install &lt;/span&gt;jethrokuan/z             &lt;span class="c"&gt;# Jump around the folders&lt;/span&gt;
fisher &lt;span class="nb"&gt;install &lt;/span&gt;decors/fish-colored-man
fisher &lt;span class="nb"&gt;install &lt;/span&gt;oh-my-fish/plugin-peco    &lt;span class="c"&gt;# Ctrl + R for searching history&lt;/span&gt;
fisher &lt;span class="nb"&gt;install &lt;/span&gt;oh-my-fish/plugin-extract
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that some of Fish plugins are enabled by default and there is no need to set the up like in ZSH.&lt;/p&gt;

&lt;p&gt;I also found below plugins useful while converting my &lt;code&gt;.zshrc&lt;/code&gt; (&lt;em&gt;though you may won't need them&lt;/em&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fisher &lt;span class="nb"&gt;install &lt;/span&gt;reitzig/sdkman-for-fish
fisher &lt;span class="nb"&gt;install &lt;/span&gt;lilyball/nix-env.fish
fisher &lt;span class="nb"&gt;install &lt;/span&gt;jorgebucaran/nvm.fish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Prompt
&lt;/h3&gt;

&lt;p&gt;I use Starship which is "Cross-Shell Prompt" so my configurations for Starship are automatically applied. To enable it, just use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"starship init fish | source"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.config/fish/config.fish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benchmarks
&lt;/h3&gt;

&lt;p&gt;Using hyperfine at first run, I've noticed Fish is faster than ZSH to some extent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7kl9a6td56izvugtowl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7kl9a6td56izvugtowl.png" alt="Benchmark results using Hyperfine on both ZSH and Fish" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 (&lt;em&gt;manages multiple Java Distributions similar to NVM&lt;/em&gt;). &lt;/p&gt;

&lt;p&gt;Once SDKMan is removed for both shells, I re-ran benchmarks again:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j5m4pg9jqpl5kdqsdb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8j5m4pg9jqpl5kdqsdb1.png" alt="Benchmark results using Hyperfine on both ZSH and Fish" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With both shells being almost similar in my setup, Fish shell ran &lt;strong&gt;3&lt;/strong&gt; times faster than ZSH.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto suggest command completions (&lt;code&gt;fish_update_completions&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CTRL&lt;/code&gt; + &lt;code&gt;R&lt;/code&gt; with Peco for searching history easily&lt;/li&gt;
&lt;li&gt;Great plugins&lt;/li&gt;
&lt;li&gt;Faster compared to my ZSH&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Gotchas
&lt;/h3&gt;

&lt;p&gt;Although converting configurations was extremly fast, I spent a lot of time on following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I keep backups of ZSH history dating back several years. There is a tool to convert &lt;a href="https://github.com/rsalmei/zsh-history-to-fish" rel="noopener noreferrer"&gt;ZSH history to Fish&lt;/a&gt;, but it didn't kept timestamp of execution. Also, some of multiline commands
(&lt;em&gt;such as &lt;code&gt;curl&lt;/code&gt;&lt;/em&gt;) broke &lt;code&gt;fish_history&lt;/code&gt; file. The tool works, but may have to manually correct errors.&lt;/li&gt;
&lt;li&gt;Poetry completions produce &lt;a href="https://github.com/python-poetry/cleo/issues/84#issuecomment-1255627939" rel="noopener noreferrer"&gt;errors&lt;/a&gt;. I though it was error something due to Fish, but found out later that this will be fixed.&lt;/li&gt;
&lt;li&gt;Some of the builds scripts (Makefiles, builds tasks...) exported certain ENV variables using &lt;code&gt;export&lt;/code&gt; so running it with Fish produced errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;At the end, I suggest you try it. If it doesn't work, you can always go back to your previous configuration.&lt;/p&gt;

</description>
      <category>fish</category>
      <category>zsh</category>
      <category>shell</category>
      <category>terminal</category>
    </item>
  </channel>
</rss>
