I've been using Zsh for a few years, and that experience has been made much more pleasant by also using Oh-My-Zsh, which is a collection of Zsh themes and plugins. One of my favorites is a feature that displays the name and status of the checked out git branch in your current directory. However, I ran into an issue with long unusually long branch names, and that sent me on a mission to make my prompt usable again.

The Issue

With Oh-My-Zsh installed, your prompt should look something like this:

Prompt with git info

However, at The Network, we have a pretty specific branch-naming convention that makes that slightly less convenient. Branch names are automatically generated by a bot and use the following convention: [team-name]-[Pivotal-Tracker-story-name]-[PivotalTrackerID]

With a branch like that, our Zsh prompt looks more like:

Prompt with excess git info

Clearly that's not ideal. But, with Oh-My-Zsh's plugin system, we can fix it.

The Fix

The branch information for the Zsh prompt is coming from the function git_prompt_info in oh-my-zsh/lib/git.zsh.

The standard version looks like this:

function git_prompt_info() {  
  if [[ "$(command git config --get oh-my-zsh.hide-status 2>/dev/null)" != "1" ]]; then
    ref=$(command git symbolic-ref HEAD 2> /dev/null) || \
    ref=$(command git rev-parse --short HEAD 2> /dev/null) || return 0
    echo "$ZSH_THEME_GIT_PROMPT_PREFIX${ref#refs/heads/}$(parse_git_dirty)$ZSH_THEME_GIT_PROMPT_SUFFIX"
  fi
}

Now, we want to modify that in a couple of ways. First, we want to have a maximum length for the display string. 20 seems like a reasonable length. Next, we want to be able to strip out the leading team name depending on a configuration. It doesn't make much sense to take up 3 or 4 characters of the branch name with a team name that rarely changes per-developer. Finally, we want to ensure that our final displayed string contains the ID at the end so that we can easily link the branch back to the Pivotal Tracker story. As an overall goal, we'd also like to keep the options configurable and flexible enough that it can be used for naming conventions that aren't exactly like ours.

As a first step, we can create our plugin inside of the oh-my-zsh/custom/plugins directory. These plugins can override built-in functionality and plugins.

After that, we check to see if the branch name is even long enough to worry about. The maximum length is pulled from a git config setting, with a fallback to 20 if it's not set. If the branch name is short enough, we can skip everything else. Otherwise, we need to work on trimming it down.

Next, we want to implement the functionality that strips the team name. To do that, we look for a regex in our git config and, if we find one, remove the first match using sed. In our case, the regex we want to use to strip the team name is [^-]*-, which will match everything up to and including the first dash.

Finally, we want to truncate our branch name if it's still too long. The length of the ID is also stored in a git config setting, and we can use that to calculate the substrings we want to keep or discard. Using cut, we can trim the name down to some of the leading characters, add a ..., and then the ID, leaving us with a string of the appropriate length. Boom!

Prompt with trimmed git info

Conclusion

After we've got it completed, we can add a basic install script that puts the plugin in the correct directory and optionally configures the plugin to use the correct settings for The Network's naming conventions. You can see the final code on GitHub.