Writing Shell Functions in zsh

If you want to customize your zsh experience (and you have oh-my-zsh installed), you should know how to extend your shell with custom functions.

First you need to create a plugin in ~/.oh-my-zsh/plugins/yourplugin/yourplugin.plugin.zsh - and include the plugin in the list of installed plugins in ~/.zshrc

Simple functions

In zsh (as in bash) function parameters are named $1 for the first, $2 for second and so forth. This means you can easily make a custom function to several things to the same (set of) paramter(s). e.g.

This allows you to call mkp projectname, and get the project created in ~/Documents/Projects, get git init called, and cd into that directory, ready to work.

You do not need to rely on direct input to a shell script however. This example shows how to parse the current directory, and use that as a custom parameter.

This reads the current directory, and uses basename to get only the name of the directory (instead of the complete path). This could be used to rsync static sites to (and from) a webserver. The webserver variable should contain the complete ssh-path to the common directory of sites, and the appended sitename will be the directory of the specific site.

Autocompletion

Basic autocompletion is made with compdef and compadd. Compdef is used to define a completion, it takes two paramters. The function to call when autocompleting, and the command to autocomplete. The compadd function is used to add items to a list of things to autocomplete to. Used in combination you can make your own autocompletion of commands, where the default autocompletion (file paths) would not suffice. e.g.

A lot is happening here, so let me briefly explain.

  • reset is a custom function to reset a specific file in a git repo

  • gdl is a command to git diff a specific file in a git repo

  • the gitdiff and gitreset commands are both parsing the git status –short list, to allow to autocomplete to changed files only.

  • the two compdef statements tells zsh that when running gdl or reset, it should autocomplete with gitdiff and gitreset respectively

Command history

Back in spring of last year, I spent a couple of days trying to figure out how to access the command history. I use this extensively for my git workflow.

You can read the history quite easily:

$history contains the complete history, and $HISTCMD is the next index, thus $HISTCMD-1 is the last entered command.

Knowing this means it is easy, to e.g. get the last parameter of the last command.

This means you can run gdl and get autocompletion of the path, and then when you have seen the diff, you can decide wether to git add (gal) or git checkout (gcl) the file.