Artboard 16Google Sheets iconSwift icon
Published at
Updated at
Reading time
2min

Suppose you're working on multiple projects: apart from npm start, it's very common that projects include very specific commands. There might be make, last week a looked at grunt and the "best ones" rely on cryptic command variables or flags.

Nate Meyers' jog eases navigating all these projects.

jog allows accessing commands from your history filtered by the current working directory. 😲 What a beautiful idea!

The project doesn't come with an automated setup and boils down to two shell functions.

# write all commands and the directory they've been run in to `.zsh_history_ext`
function zshaddhistory() {
  echo "${1%%$'\n'}${PWD}   " >> ~/.zsh_history_ext
}

# filter commands by the current working directory
function jog() {
  grep -v "jog" ~/.zsh_history_ext | grep -a --color=never "${PWD}   " | cut -f1 -d"⋮" | tail
}

The zshaddhistory shell hook runs before anything is written to the default history file (~/.zsh_history). You can leverage this hook to create another history file that includes the ran command but also the directory it was used in.

jog then filters all entries and presents the ones run in the current working directory.

That's great and all, but I went on and tweaked things a little bit.

An interactive directory history

I adjusted the jog functions and added/changed the following:

  • rename jog to lc ("last commands" – way better!)
  • store entries in ~/.lc_history
  • filter useless history entries (ls, git, cd, etc.)
  • bring in fzf for some nice interactivity

Be warned; I'm not a shell expert, but my "try and error script" below works fine. (I'm up for improvements, though!)

# things for the `lc` command
LC_DELIMITER_START="⋮";
LC_DELIMITER_END="⭐";

# write current command location to `.lc_history` whenever a command is ran
# `.lc_history` is used in `lc` command
function zshaddhistory() {
  # ignore empty commands
  if [[ $1 == $'\n' ]]; then return; fi

  # ignore specific commands
  local COMMANDS_TO_IGNORE=( ls ll cd j git gss gap lc ggpush ggpull);
  for i in "${COMMANDS_TO_IGNORE[@]}"
  do
    if [[ $1 == "$i"* ]]; then
      return;
    fi
  done

  echo "${1%%$'\n'}${LC_DELIMITER_START}${PWD}${LC_DELIMITER_END}" >> ~/.lc_history
}

# `lc` – last command
function lc() {
  SELECTED_COMMAND=$(grep -a --color=never "${PWD}${LC_DELIMITER_END}" ~/.lc_history | cut -f1 -d "${LC_DELIMITER_START}" | tail -r | fzf);

  # handle case of selecting no command via fzf
  if [[ ${#SELECTED_COMMAND} -gt 0 ]]; then
    echo "Running '$SELECTED_COMMAND'..."
    echo "**************************"
    eval " $SELECTED_COMMAND";
  fi
}

Before you copy the snippet above, make sure to have a look at my .zshrc file to see the most recent implementation. I'll continue tweaking it.

And with that, have fun!

Was this snippet helpful?
Yes? Cool! You might want to check out Web Weekly for more snippets. The last edition went out 3 days ago.

Related Topics

Related Articles