Don't Lose Your Head With iTerm2

Written by alonn24 | Published 2018/06/11
Tech Story Tags: git | iterm2 | terminal | lifehacks | productivity

TLDRvia the TL;DR App

iTerm2 is a terminal app I use to run everything in my MacOS. iTerm2 is a replacement for Terminal providing a lot of features with variety of themes that changes the look and feel. I run everything in iTerm2, from git commands to running live servers, searching texts end edit files. But one thing is always disturbing me— running long processes. Long processes alway hide the current prompt and with it the working directory. I installed Oh My Zsh and it added this nice prompt that displays the current working directory and the git branch I’m using, but when running long processes the prompt gets out of the buffer zone an I’m left clueless.

Everything loses context in the terminal once you run a process — the status bar shows the running task and if the task is verbose enough the prompt gets out of the buffer zone and is not visible. The status bar, the tab name and everything I can think of just wont show the current working directory or anything about where I’m at. I can not even run pwd because a process is running.

One thing I often do is running tasks with & at the end of the command, for example npm i &, which runs the process in the background and leave the prompt available for interactions. You can run a several process in parallel by adding & between them. When a process runs in the background you can not break it with cmd+C, instead you need to explicitly kill it with kill [pid] or killall [name] command. I am running killall node sometimes but that kills all of the node processes running everywhere.

To kill a specific process you need to know the pid and to to do that you need to remember what you are running. You can run ps -ef | grep [what you are running] to get the pid, for example ps -ef | grep node will give you all the node processes. iTerm2 provides a panel that shows all the processes with the pids for every panel. Just hit cmd+shft+B or Toolbelt → Show Toolbelt, then check the Toolbelt → Jobs to see the jobs panel containing the names of the processes and the pid for each one.

To kill a process you can select it and press select signal → kill, or execute kill [pid] in the console knowing the exact pid from the panel.

One small problem I have with running many processes in parallel is the output — its not neat and hard to understand because the output stream get updates from different processes. I prefer to run a blocking processes and just know where I am at all time. There is a solution to the problem using iTerm2 badges.

A badge is a large text label that appears in the top right of a terminal session. You can update that text using iTem2 → Preferences → Profiles → General → Badge.

The badge can have static value, like in the example above, and dynamic value via script variables. Lets try to achieve what we wanted in the first place, we will try to set the badge to the following: [git repo] git:([git branch]) just like I have in my prompt.

We would like to create some kind of a variable that will contain the text, and set it to the badge field. To create and update variables we need to install the iTerm2 shell integration. It is a common integration and can be installed with iTem2 -> Install Shell Integration.

Shell integration allows to create variables and use them, we would like to create a variable that will hold the badge text just as we described. In the configuration startup script, for me it’s ~/.zshrc, add the following:

function iterm2_print_user_vars() {iterm2_set_user_var gitStatus "$(gitStatus)"}

function getGitStatus {if [[ $(git status 2> /dev/null) = "" ]] thenecho "$(topDir)"else echo "$(getGitProjectDir)$(topDir) git:($(getGitBranch))$(isGitBranchDirty)"fi}

function getGitProjectDir {basename $(git rev-parse --show-toplevel 2> /dev/null ) 2> /dev/**null**}

function topDir {if [[ $(basename $(pwd)) = $(getGitProjectDir) ]] thenecho ""else echo "/$(basename $(pwd))"fi}

function getGitBranch {basename $(git branch 2> /dev/null | grep \* | cut -c3-) 2> /dev/**null**}

function isGitBranchDirty {[[ $(git diff --shortstat 2> /dev/null | tail -n1) != "" ]] && echo "⚡ "}

The first function — item2_print_user_vars is the main function here and will run after any command running in the terminal. It updates gitStatus variable with what we wanted using the following functions:

getGitStatus — returns the current directory if it’s not a git repository.

getGitProjectDir — returns the git repo name.

topDir — returns the current directory if it’s not the main repo folder. It is useful for monorepos when the real project in a subdirectory in the main repo directory.

getGitBranch — returns the current git branch.

isGitBranchDirty — return “⚡ “ if we have panding changes.

Now to use the variable we created we just need to add it to the badge text as we did before with a static value. we will add it as the badge text in iTerm2 →Preferences →Profiles →general →Badge insert \(user.gitProjectDir) and walla! next time anything changes you will see it in a badge in you terminal and never lose you head.


Published by HackerNoon on 2018/06/11