A directory-dependent and interactive command history
- 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 (~/
). 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.
I adjusted the jog
functions and added/changed the following:
- rename
jog
tolc
("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
file to see the most recent implementation. I'll continue tweaking it.
And with that, have fun!
Join 5.5k readers and learn something new every week with Web Weekly.