I spend a lot of time on the terminal. I started with vanilla terminals on Ubuntu and macOS. Later I learned about terminals with a few "batteries" included like iTerm2 and HyperJS. I have also used tmux extensively before, but ended up switching a few months later to use window splitting from iTerm2 and also profiles, which can login to a shell session automatically. Well, enough of history.

This post will introduce you to a basic shell configuration. Ok, it is not basic. However, for me it is the difference between bearing and loving my terminal setup. Topics I will talk about are the following:

I will build this configuration starting from a vanilla Ubuntu 18.04 installation.

If you just want to check the dotfile: check this gist.

Oh My Zsh

I used vanilla bash for quite a few years without even caring about what it was. I found out oh-my-zsh, which had incredible features, and switched to zsh just to use it. The end. You may be able to find similar packages for bash (oh-my-bash is a thing), but I never tried them.

I can't live without oh-my-zsh mainly for two reasons:

  1. Themes
  2. Aliases Some examples of aliases I love are presented below. You can see just how much characters I avoid typing.
  ga='git add'
  gc='git commit -v'
  gc!='git commit -v --amend'
  gca='git commit -v -a'
  gca!='git commit -v -a --amend'
  gcb='git checkout -b'
  gcm='git checkout master'
  gcd='git checkout develop'
  gd='git diff'
  gdca='git diff --cached'
  gds='git diff --staged'
  gf='git fetch'
  gfa='git fetch --all --prune'
  gfo='git fetch origin'
  gl='git pull'
  glg='git log --stat'
  gm='git merge'
  gp='git push'
  gpf!='git push --force'
  gss='git status -s'
  gsw='git switch'
  gswc='git switch -c'
  ..=cd ..
  -='cd -'

Installing

  • Install zsh and change default shell
sudo apt install zsh && chsh --shell /bin/zsh
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

The Best Zsh Plugins

These four plugins help you reuse your commands and find mistakes while typing. They make your shell be a little more like fish shell. By the way, I tried fish before, but it is not POSIX compatible and copying commands from others started to be a pain, as I always had to do some minor editing for things like VAR=2 run_command.

I think the most striking command of the 4 is history-search-multi-word. It improves the Ctrl + R shortcut, giving you fuzzy search over your history! Thank me later.

To install them, we are going to use a plugin manager called zinit.

  sh -c "$(curl -fsSL https://raw.githubusercontent.com/zdharma/zinit/master/doc/install.sh)"

  echo 'zinit load "zdharma/history-search-multi-word"' >> ~/.zshrc
  echo 'zinit load "zsh-users/zsh-history-substring-search"' >> ~/.zshrc
  echo 'zinit load "zsh-users/zsh-autosuggestions"' >> ~/.zshrc
  echo 'zinit load "zsh-users/zsh-syntax-highlighting"' >> ~/.zshrc

Other Zsh Plugins

I don't consider the plugins below essential, but they are nice.

colorize

Colorize allows you to cat files with syntax highlighting. You can install it via:

  echo 'export GOPATH=$(go env GOPATH)' >> ~/.zshrc
  echo 'export PATH=$GOPATH/bin:"$PATH"' >> ~/.zshrc
  echo 'export ZSH_COLORIZE_TOOL=chroma' >> ~/.zshrc

  sudo add-apt-repository ppa:longsleep/golang-backports
  sudo apt update
  sudo apt install golang-go
  source ~/.zshrc
  go get -u github.com/alecthomas/chroma/cmd/chroma

After the above, you should add colorize to the plugins variable in ~/.zshrc.

Colorize supports syntax-highlighting via pygments and chroma. Chroma has less features, but is written in go and seems faster than pygments, so I use it.

To test colorize, you can try ccat (color cat?) with any code file you have, or you could do:

  echo '#include<stdio.h>\nint main() {\n  printf("Hello World"\n);\n}' > test.c
  ccat test.c

colored-man-pages

The name says it all: colors in man pages.

To install it: add colored-man-pages to the plugins variable in ~/.zshrc.

To test it: man less or any other man-page. You should see some colors.

copyfile

Allows you to copy a file to the clipboard from the terminal.

To install it: add copyfile to the plugins variable in ~/.zshrc.

To test it: copyfile test.c and then try to paste is somewhere.

gitignore

You can search for gitignore files for certain languages from your terminal and add them to your project.

To install it: add gitignore to the plugins variable in ~/.zshrc.

To test it: gi list to see all keywords. gi swift > swift.gitignore to see an example file.

Default EDITOR

Every time I install an OS from scratch and type git commit, I see the EDITOR defined in this variable pop up. Sometimes, the default is nano, which I dislike. I usually leave vim as the default, but you can set whatever.

The dotfile from Oh-my-zsh has some commented lines setting up that variable, just make sure to uncomment them and set to your favorite editor:

  if [[ -n $SSH_CONNECTION ]]; then
      export EDITOR='vim'
  else
       export EDITOR='mvim'
  fi

I usually change mvim by vim as well.

Fancy (and fast) command line tools

GNU Tools?

Imagine the gnu tools find, ls and grep. Now, imagine they are all faster and have sensible defaults for git repositories (like not searching ignored files). These tools are:

All the tools above are written in rust. They are all available in homebrew for macOS, but not in the default ubuntu repos. I ended up installing them on Linux using cargo, which requires you to install rust. If you are fine with that, follow the instructions below:

  # Install rust via rustup
  # More info in https://www.rust-lang.org/tools/install
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  # Install command line tools
  cargo install exa fd-find ripgrep

Fuzzy File Finding

FZF allows you to find files, like find and fd, but you can do fuzzy searches and it shows you the list of candidates while you type. There is also a plugin for vim, which is super helpful and is the way I use this plugin the most. For more info, including about the vim plugin, check the README on git.

To install it:

  git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
  ~/.fzf/install

Spacemacs

There is much to love in emacs. However, customizing it is quite an ordeal. I prefer to have an editor with sensible defaults and then I just tweak a few details. Spacemacs allows me to have just that for emacs, which is awesome.

To install it: get emacs 26 and then clone the develop spacemacs repo. I recommend the develop branch because the community keeps adding incredible stuff in that branch that will take a very long time to get to master.

  sudo add-apt-repository ppa:kelleyk/emacs
  sudo apt update
  sudo apt install emacs26
  git clone -b develop https://github.com/syl20bnr/spacemacs ~/.emacs.d

There is much to learn about this one. Check the docs for more info. Some shortcuts I like:

SPC p p
pick a project and find files in it; any git repo you accessed before with emacs is automatically added to the repo list
SPC b b
open recent buffer; even if you closed files, you can easily open them if you remember part of the name

There are also several shortcuts for org-mode and other modes.

File Conversion

I created a few aliases that help me with file conversions that I do frequently, namely:

  • markdown2org
  • markdown2html
  • mov2mkv

If you want them:

  curl -fsSL https://gist.githubusercontent.com/ataias/9dfac5c50f71b8207c9abcab265d41a7/raw/98fe0cc665deb3860b613c7ab57df2953c2bd702/conversion-aliases.zsh > ~/.conversion-aliases.zsh
  echo 'source ~/.conversion-aliases.zsh' >> ~/.zshrc

You need to have pandoc and ffmpeg installed, by the way.

Conclusion

We learned how to set up the basic shell given to us in a Unix machine. When third party packages were necessary, we used apt or a plugin manager for them. The instructions are easily convertible to macOS using the homebrew package manager. The final ~/.zshrc file is in this gist.

I hope you enjoyed this post. I appreciate any constructive feedback and I would love to hear any tweaks you made to this configuration, or tell me more about your own.