#308 Oh My ZSH
- Download:
- source codeProject Files in Zip (2.18 KB)
- mp4Full Size H.264 Video (25.9 MB)
- m4vSmaller H.264 Video (11.2 MB)
- webmFull Size VP8 Video (11.7 MB)
- ogvFull Size Theora Video (23.5 MB)
As Rails developers we frequently use the command line but we don’t always get the most out of it. The default shell for a lot of UNIX-based systems is Bash and one of the best things you can do is switch from this to Z Shell (zsh). This can be a little difficult but there’s a project called oh-my-zsh which makes it easy to install zsh with a nice default configuration and some plugins and themes. All we need to do to switch is to run this command in the terminal:
wget --no-check-certificate https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
If we don’t have wget
installed on your system we can install zsh via curl
instead by running this command instead.
curl -L https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh | sh
This will clone the oh-my-zsh repository and install it for us, though we’ll need to enter our password as it does. Once it’s finished we can open a new terminal window and it should be a zsh window.
The first thing to notice is that the prompt looks considerably different. We can customize this fully through themes and we’ll show you how to do this later. Although zsh looks different, for the most part it behaves just like Bash and the commands we use there will work exactly the same in zsh.
A Quick Tour of zsh’s Features
One of the best features of zsh is the smart autocompletion. If, for example, we type ls -
then hit TAB we’ll get a list of the options that ls
takes. We can even use the cursor keys to scroll through the list and complete our command. This feature is especially useful for more complex commands such as git commit
.
➜ ~ git commit - --all -a -- update all paths in the index file --allow-empty -- allow recording an empty commit --amend -- amend the tip of the current branch --author -- override the author name used in the commit --cleanup -- specify how the commit message should be cleaned up --edit -e -- edit the commit message before committing --file -F -- read commit message from given file --include -i -- update the given files and commit the whole index --interactive -- interactively update paths in the index file --message -m -- use the given message as the commit message --no-verify -n -- do not look for suspicious lines the commit introduc --only -o -- commit only the given files --quiet -q -- suppress commit summary message --reedit-message -c -- use existing commit object and edit log message --reuse-message -C -- use existing commit object with same log message --signoff -s -- add Signed-off-by line at the end of the commit mess --untracked-files -u -- show files in untracked directories --verbose -v -- show unified diff of all file changes
Another useful feature is the ability to specify more extensive wildcard options. If we want to list all of the Ruby files in a Rails project we can use a double asterisk to do deeply-nested directory searching.
➜ railscasts git:(master) ls **/*.rb app/controllers/application_controller.rb app/controllers/comments_controller.rb app/controllers/episodes_controller.rb app/controllers/feedback_messages_controller.rb app/controllers/info_controller.rb app/controllers/users_controller.rb app/controllers/versions_controller.rb app/helpers/application_helper.rb app/helpers/comments_helper.rb app/helpers/episodes_helper.rb app/helpers/error_messages_helper.rb app/helpers/feedback_messages_helper.rb # rest of files omitted.
There are other great features that zsh provides. Some of these are specific to OS X. For example, there’s more information in the title bar about the current user, machine and directory.
There are a number of other useful small features, too. If we open a new terminal tab it will open in the same directory as the previous tab’s current directory. Also, if we start typing a command and then press the up arrow the command will auto-complete based on the command history.
Configuring zsh
All of these features can be configured so we’ll look next at how to do that. There’s a .zshrc
file in our home directory which is loaded when we start a new zsh session.
# Path to your oh-my-zsh configuration. ZSH=$HOME/.oh-my-zsh # Set name of the theme to load. # Look in ~/.oh-my-zsh/themes/ # Optionally, if you set this to "random", it'll load a random theme each # time that oh-my-zsh is loaded. ZSH_THEME="robbyrussell" # Set to this to use case-sensitive completion # CASE_SENSITIVE="true" # Comment this out to disable weekly auto-update checks # DISABLE_AUTO_UPDATE="true" # Uncomment following line if you want to disable colors in ls # DISABLE_LS_COLORS="true" # Uncomment following line if you want to disable autosetting terminal title. # DISABLE_AUTO_TITLE="true" # Uncomment following line if you want red dots to be displayed while waiting for completion # COMPLETION_WAITING_DOTS="true" # Which plugins would you like to load? (plugins can be found in ~/.oh-my-zsh/plugins/*) # Example format: plugins=(rails git textmate ruby lighthouse) plugins=(git) source $ZSH/oh-my-zsh.sh # Customize to your needs... export PATH=/Users/eifion/.rvm/gems/ruby-1.9.2-p290/bin:/Users/eifion/.rvm/gems/ruby-1.9.2-p290@global/bin:/Users/eifion/.rvm/rubies/ruby-1.9.2-p290/bin:/Users/eifion/.rvm/bin:/Users/eifion/bin:/usr/local/bin:/usr/local/mysql/bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
This file first sets the path to oh-my-zsh’s configuration directory and then sets the theme, which is currently robbyrussell
. Below this are some commented-out options so if, for example, we want to disable colours in directory listings we can uncomment the DISABLE_LS_COLORS
option.
Further down the file is a list of the currently enabled plugins. We only have git
enabled for now, but we’ll add more shortly. The line below that, source $ZSH/oh-my-zsh.sh
, loads oh-my-zsh and finally there’s the line that configures our PATH
. This defaults to whatever value it had when we installed oh-my-zsh but it’s better to carry this over from our Bash profile. We can do this by removing the line that begins with export PATH
from .zshrc
and then running this command.
➜ ~ cat ~/.bash_profile >> ~/.zshrc
Obviously these settings will be different for your own machine. Most of the time you should be able to copy them straight across but occasionally they’ll need to be adjusted slightly to work.
Themes
Next we’ll create a new theme so that we can change the way the prompt looks. The available themes are listed in the ~/.oh-my-zsh/themes
directory and there’s a large number in the default installation. To see what they look like there’s a list of themes with screenshots on the oh-my-zsh wiki page. If we want to customize oh-my-zsh more thoroughly we can create our own theme by creating a new zsh-theme
file in the themes directory and we’ll do that now.
PROMPT='%3~$(git_prompt_info)%#' ZSH_THEME_GIT_PROMPT_PREFIX="[" ZSH_THEME_GIT_PROMPT_SUFFIX="]"
Our theme is fairly basic. All we do is set the prompt and a prefix and suffix for the part of the prompt that shows when the current directory is part of a Git repository. If we want to customize our theme further we can look at the source for the other themes for inspiration. There’s also a useful page that has documentation on the various characters we can pass into the PROMPT
option and what they do. To see our theme we’ll need to change the ZSH_THEME
option in the the .zshrc
file to match our theme’s name.
ZSH_THEME="eifion"
Plugins
It’s easy to extend zsh with plugins. As is the case with themes a large number of plugins are supplied in the default installation, this time in the ~/.oh-my-zsh/plugins
directory. Before we add one it’s a good idea to look in its directory to see what it does. We’ll take a look at the Bundler plugin. This plugin has a _bundler
file and if a plugin has a file that begins with an underscore it means that it adds some autocomplete functionality to a command. This plugin does a few other things, too. It add some aliases to common Bundler commands and it also makes sure that a number of common Rails-related commands are run through bundle exec
so that we don’t need to type this each time we run one of them.
There are a number of plugins that are worth using. The brew
plugin adds some autocompletion behaviour as goes the gem
plugin. Some of the others are less useful, such as the rails3
and ruby
plugins which just add some aliases. To add plugins we just need to add them to the plugins
option in the .zshrc
file like this:
plugins=(git bundler brew gem)
We can also create our own plugins. We keep all of our projects in a ~/code
directory and having to type cd ~/code/<project>
each time we want to move to a project’s directory is a bit of a pain. We’ll set up a c
command that will enable us to move to a project’s directory more easily. We can create custom plugins in the ~/.oh-my-zsh/custom/plugins
directory. We’ll need a directory for the plugin and a .plugin.zsh
file, too.
c() { cd ~/code/$1; } _c() { _files -W ~/code -/; } compdef _c c
The first line above defines the c
command for us and it simply sets the current directory to whatever subdirectory of the code
directory we pass in as an argument. The second line gives us autocompletion for the command. To add autocompletion to a command we need to create another command with the same name but prefixed with an underscore. Our _c
command delegates to the _files
completion behaviour and will autocomplete based on the files in the ~/code
directory. The final line above defines the completion by saying that _c
should be used as the autocompletion command for c
.
For our plugin to be available we need to add it to the plugins option in our .zshrc
file.
plugins=(git bundler brew gem eifion)
We’ll need to open a new terminal window for the changes to take effect. Once we have we can use our new command.
That’s it for our episode of oh-my-zsh. If you use the shell much it’s well worth considering replacing your system’s default shell with zsh.