ZSH on OS X

ZSH on OS X

These are the steps I followed for installing and customizing ZSH on 10.7 Lion.

Installation Instructions

Install a new version of zsh through MacPorts

OS X Lion comes with a newer version of zsh (4.3.11) in /bin, but if you want to maintain a current version, you can install it from MacPorts (or Fink or Homebrew depending on which package manager you prefer). The syntax is similar. For MacPorts,

sudo port install zsh-devel +mp_completion +examples +dec +pcre

MacPorts will install zsh in /opt/local/bin/zsh. Unfortunately, OS X will not recognize zsh as a login shell until /etc/shells is edited to include /opt/local/bin/zsh. My /etc/shells reads

# List of acceptable shells for chpass(1).
# Ftpd will not allow users to connect who are not using
# one of these shells.

/bin/bash
/bin/csh
/bin/ksh
/bin/sh
/bin/tcsh
/bin/zsh
/opt/local/bin/zsh

/etc/shells is a protected file and can only be edited with admin or root privaleges.

sudo gvim /etc/shells

Alternatively,

sudo sh -c "echo '/opt/local/bin/zsh' >> /etc/shells

Change the default shell to zsh

Option 1 (preferred): In Terminal.app, execute

chsh -s /opt/local/bin/zsh

Option 2: You should also be able to make the change through System Preferences -> Users & Groups. Unlock the pane (lower left corner). Right click on your account and select “Advanced Options…” (note: if the pane is not unlocked, the contextual menu will not appear).

Your default shell can be changed from the opened dialog

These are the steps I followed for installing and customizing ZSH on 10.7 Lion.

Install ZSH Templates

There are two main template packages that can be added to zsh. These packages extend the default functionality of ZSH. Please see their documentation for further information. The packages:

  • Oh My Zsh: “A community supported framework for managing your ZSH installation.” Oh-my-zsh provides a growing collection of plugins and addons that enhance your zshell.
  • zsh-templates-osx: “A collection of files that help the user to customize the zsh shell for the Mac OS X operating system”

I originally tried using zsh-templates-osx. The instructions are simple: a custom /private/etc/zshrc and /private/etc/zshenv are downloaded and written with appropriate root permissions. These files are sourced with new login shells (see this article).

cd /private 
sudo svn co http://zsh-templates-osx.googlecode.com/svn/trunk/etc 

The template files are added to /Library/init/zsh.

cd /Library 
sudo svn co http://zsh-templates-osx.googlecode.com/svn/trunk/Library/init 

I had a few problem with the install, including problems with the order of my bin directories in $PATH (zsh-templates-osx sets variables through path_helper), environment variables, and the sourcing of etc/zshrc and etc/zshenv. I’m assuming that the error lies on my end. If you have an idea, please leave me a comment.

I settled on oh-my-zsh. Installation was also simple. Directly from their website:

Step 1: Clone the repository. Templates files are copied to a hidden directory ~/.oh-my-zsh in your $HOME directory.

git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh

Step 2: Backup your ~/.zshrc

cp .zshrc .zshrc_backup

Step 3: Copy their .zshrc to your $HOME.

cp ~/.oh-my-zsh/templates/zshrc.zsh-template ~/.zshrc

Step 4: Add back any customizations from your original .zshrc (now .zshrc_backup) file back to their .zshrc.

Oh-my-zsh actives the wonderful tab-completion, history, and directory navigation features of ZSH by default. Any further changes to your user experience is straight forward: themes and additional plugins can be loaded through ~/.zshrc and further modifications can be added to .zsh files in ~/.oh-my-zsh/lib. To change your theme and add additional plugins, edit

ZSH_THEME="robbyrussell"

to change your theme. A list of current themes is maintained here. Additional plugins can be added. Edit plugins=(list of plugins) in ~/.zshrc.

plugins=(git osx macports)

A full list of plugins is maintained here.

Additional aliases and settings are placed into ~/.oh-my-zsh/lib as a group of files with .zsh suffixes. Any file with this suffix will be sourced. These files (for example aliases.zsh) can be freely edited.

Further additions to zshrc

Fortunately, oh-my-zsh turns on most of features a common user will need. Most of my additions were $PATH additions for ROOT, MacPorts and X11, required environment variables, and my dircolor settings (see below).

The only noteworthy additions are the automatic ls after a cd as suggested by a post on StackOverflow, and the ordering of my PATH variables.

# Path additions
# List items in the reverse order you want them to appear in $PATH (i.e. last
# items appear first ).
PATH=/usr/X11/bin:$PATH     # X11 Stuff
PATH=$ROOTSYS/bin:$PATH     # ROOT Data Analysis Framework
PATH=/opt/local/bin:$PATH   # MacPorts
PATH=/opt/local/sbin:$PATH  # MacPorts
PATH=/usr/local/bin:$PATH   # User binaries
PATH=$HOME/bin:$PATH        # Personal binaries

export PATH


# List directory contents after a 'cd'
function chpwd() {
    emulate -LR zsh
    ls
}

Add greater color customization through dircolors

Although oh-my-zsh provides a default color scheme, I prefer the greater customization provided by dircolors. dircolors is not included in the base 10.7 distribution. An integrated dircolors and ls must be installed. This combination is included an integrated component of of the GNU core utilities package (coreutils), a suite of basic file, shell, and text manipulation utilities (see GNU Operating System coreutils). coreutils can be installed through MacPorts.

Here's an overview of the procedure we will follow:

  1. Install coreutils through macports
  2. Create a custom .dir_colors file in your $HOME enumerating your color choices
  3. Ensure your $TERM type is included in .dir_colors
  4. Edit ~/.zshrc to evaluate dircolors when ls is called
  5. Alias your ls to include the --color flag.
  6. Adjust oh-my-zsh

First, install coreutils

sudo port install coreutils

Please install without the +with_default_names option. +with_default_names uses the regular names for new standard unix programs rather than prefacing them with a 'g', e.g. ls instead of gls. This is a problem if MacPorts is ever updated. Please see my post here.

After the installation of coreutils, create a ~/.dir_colors file.

touch ~/.dir_colors

I have included mine below, adapted and designed for text on a black terminal. Please make sure that your TERM is included in the .dir_colors header. To see your version of TERM:

echo $TERM

For my computer the result was xterm-256color. Your Terminal type can be changed in Terminal Preferences.

My ~/.dir_colors file


# DIRCOLOR file for the mac.
# Designed for a text on black terminal.

# Below, there should be one TERM entry for each terminal
# type that can be colored.
TERM linux
TERM linux-c
TERM mach-color
TERM console
TERM con132x25
TERM con132x30
TERM con132x43
TERM con132x60
TERM con80x25
TERM con80x28
TERM con80x30
TERM con80x43
TERM con80x50
TERM con80x60
TERM dtterm
TERM xterm
TERM xterm-color
TERM xterm-256color # Default for OS X 10.7
TERM xterm-debian
TERM rxvt
TERM screen
TERM screen-bce
TERM putty
TERM screen-w
TERM vt100
TERM Eterm

COLOR yes

# Below are the color init strings for the basic file types. 
# A color init string consists of one or more of the following
# numeric codes:
# 
# Attribute codes:
#     00=none 01=bold 04=underscore 05=blink 07=reverse
#     08=concealed
# Text color codes:
#     30=black 31=red 32=green 33=yellow 34=blue 35=magenta
#     36=cyan 37=white
# Background color codes:
#     40=black 41=red 42=green 43=yellow 44=blue 45=magenta 
#     46=cyan 47=white

NORMAL 00	    # Global default
FILE 00		    # Normal file
DIR 04;40;33        # Directory (DEFAULT: 01;34 - CHANGED S.M.)
LINK 01;36	    # Symbolic link.
FIFO 40;33	    # Pipe
SOCK 01;35	    # Socket
DOOR 01;35	    # Door
BLK 40;33;01	    # Block device driver
CHR 40;33;01	    # Character device driver
ORPHAN 40;31;01     # Symlink to nonexistent file

# This is for files with execute permission:
EXEC 01;32

# List any file extensions like '.gz' or '.tar' that you would
# like ls to colorize below. Put the extension, a space, and
# the color init string (and any comments you want to add after 
# a '#').



# USER DEFINED

# Archive files
.tar 01;31 # archives or compressed (bright red)
.tgz 01;31
.tar.gz 01;31
.arj 01;31
.taz 01;31
.lzh 01;31
.zip 01;31
.z   01;31
.Z   01;31
.gz  01;31
.bz2 01;31
.deb 01;31
.rpm 01;31
.jar 01;31

# Images and video
.fig 01;35
.jpg 01;35
.jpeg 01;35
.gif 01;35
.bmp 01;35
.pbm 01;35
.pgm 01;35
.ppm 01;35
.tga 01;35
.xbm 01;35
.xpm 01;35
.tif 01;35
.tiff 01;35
.png 01;35
.mov 01;35
.mpg 01;35
.mpeg 01;35
.avi 01;35
.fli 01;35
.gl 01;35
.dl 01;35
.xcf 01;35
.xwd 01;35

# Audio
.ogg 01;35
.mp3 01;35
.wav 01;35
.aac 01;35


# Programming
*Makefile 01;33
.C   01;33
.cpp 01;33
.cc  01;33
.c   01;33
.for 01;33
.h   01;33
.tcl 01;33
.py  01;33
.sh  01;33
.o   33
.so  33

# Documents
*README 01;37;41
*Readme 01;37;41
*readme 01;37;41
.tex 01;37;40
.dvi 01;37;40
.ppt 01;37;40
.pptx 01;37;40
.doc 01;37;40
.docx 01;37;40
.xls 01;37;40
.xlsx 01;37;40
.ps  01;37;40
.eps 01;37;40
.pdf 01;37;40
.txt 01;37;40
.htm 01;37;40
.xml 01;37;40
.pot 01;37;40
.nb  01;37;40

# Spectra (physics stuff)
.spe 32
.spn 32
.sec 32
.asc 32
.mat 32
.spc 32
.Spc 32
.root 32
.gf2 32
.gf3 32

# Data
.dat 01;04;35
.evt 01;04;35
.bin 01;04;35

# Temporary files
*~ 36
.bak 36
.tmp 36
*# 36

Add the following lines to your ~/.zshrc to ensure that dircolors runs when ls or any ls variant is called.

# Color listing
eval $(dircolors ~/.dir_colors)
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"

ls must be called with the --color flag. Modify the ls aliases in ~/.oh-my-zsh/lib/aliases.zsh.

# List direcory contents
export LS_OPTIONS='--color'
alias l='ls $LS_OPTIONS'
alias ll='ls $LS_OPTIONS -lh'
alias lll='ls $LS_OPTIONS -alh'
alias sl='ls $LS_OPTIONS' # often screw this up

Lastly, ~/.oh-my-zsh/lib/theme-and-appearance.zsh needs modified so ls is not called with the -G flag. Change alias ls='ls -G' to alias ls='ls --color, i.e.

# Enable ls colors
# Edited - S.M. Changed ls -G -> ls --color. Requires dircolor to be valid.
if [ "$DISABLE_LS_COLORS" != "true" ]
then
  # Find the option for using colors in ls, depending on the version: Linux or BSD
  ls --color -d . &>/dev/null 2>&1 && alias ls='ls --color=tty' || alias ls='ls --color'
fi

Conclusions

That should be all! Questions and comments can be addressed below.

This entry was posted in Computers, OS X, ZSH and tagged , , , . Bookmark the permalink.