Skip to content

Instantly share code, notes, and snippets.

@levihb
Last active October 23, 2020 18:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save levihb/e23dd22a48b5e94fb4d69776891d546e to your computer and use it in GitHub Desktop.
Save levihb/e23dd22a48b5e94fb4d69776891d546e to your computer and use it in GitHub Desktop.

Bash fzf directory history

render1587053748605

UPDATE: removed duplicates, now requires python

This little script allows you to access your directory history using fzf. Directory history is included for that session and for all previous sessions.

All methods of changing directories should be supported, as the script does not change cd, but just checks for a change in directory after each new command.

The history can be accessed via alt+h, and is designed to look and feel like the other key mapped bash fzf features, e.g. command history search.

Installation

Just place the script below somewhere (e.g. ~/.scripts/terminal), and then add the following line to your .bashrc

source ~/.scripts/terminal/fzf_directory_history

Environment variable settings

CD_HIST_GLOBAL

Whether to enable global directory history, or session only, true or false

CD_HIST_FILE

The file to store global history in, defaults to ~/.cd_history

CD_HIST_FZF_OPTS

Extra fzf options to use when launching the history browser

#!/usr/bin/env bash
# Get a numbered file descriptor so we're not reliant on a temp file
local_history_file="$(mktemp)"
exec {local_history}<>"$local_history_file"
rm "$local_history_file"
# reopen the file since bash can't lseek(2)
cat < /proc/self/fd/"$local_history"
local_history=/proc/self/fd/"$local_history"
# Taken from fzf's bind, not fully sure of all the details
bind -m emacs-standard '"\eh": "\C-b\C-k\C-u`__local_history__`\e\C-e\er\C-m\C-y\e \C-y\ey\C-x\C-x\C-d"'
read -r -d '' py_script << EOM
from collections import OrderedDict as od
def print_cd_history(historic_history, current_history):
cd_history = historic_history.splitlines() + current_history.splitlines()
unique = list(od.fromkeys(cd_history[::-1]))[::-1]
st = ''
for s in unique:
st += '\n' + s
print(st[1:])
pass
EOM
cd_global_history=""
pwd_prev=""
[ -z "$CD_HIST_FZF_OPTS" ] && export CD_HIST_FZF_OPTS=""
# Load previous global history if enabled
if [ -z $CD_HIST_GLOBAL ] || $CD_HIST_GLOBAL ; then
export CD_HIST_GLOBAL=true
[ -z $CD_HIST_FILE ] && export CD_HIST_FILE=$HOME/.cd_history
touch "$CD_HIST_FILE"
cd_global_history=$(cat "$CD_HIST_FILE")
else
export CD_HIST_GLOBAL=false
fi
local_history_update () {
[ "$PWD" == "$pwd_prev" ] && return
echo "$PWD" >> "$local_history"
[ "$CD_HIST_GLOBAL" = true ] && echo "$PWD" >> "$CD_HIST_FILE"
pwd_prev="$PWD"
}
__local_history__ () {
# Matches the style of other term FZF
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS $CD_HIST_FZF_OPTS"
# dir=$(echo -e "$cd_global_history""\n""$(cat "$local_history")" | fzf --tac)
current=$(cat "$local_history")
cd ~/.scripts/console/cd_history/
dir=$(python -c "$py_script""; print_cd_history(\"\"\"""$cd_global_history""\"\"\", \"\"\"""$current""\"\"\")" | fzf --tac)
[ ! -z "$dir" ] && printf 'cd %q' "$dir"
}
export PROMPT_COMMAND="local_history_update; $PROMPT_COMMAND"
@levihb
Copy link
Author

levihb commented Apr 16, 2020

render1587053748605

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment