-
Notifications
You must be signed in to change notification settings - Fork 1
/
harpoon
executable file
·161 lines (138 loc) · 4.11 KB
/
harpoon
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/sh
get_default_cache_dir() {
if [ -n "$XDG_CACHE_HOME" ]; then
echo "$XDG_CACHE_HOME"
elif [ "$(uname)" = "Darwin" ]; then
echo "$HOME/Library/Caches"
else
echo "$HOME/.cache"
fi
}
cachefile="$(get_default_cache_dir)/.tmux-harpoon-sessions"
help() {
echo
echo "Usage:"
echo " ${0##*/} [options] [args]"
echo "Options:"
echo " -a Track current tmux session"
echo " -A Track pane within current tmux session"
echo " -r <index> Replace tracked entry at index with current session"
echo " -R <index> Replace tracked entry at index with current pane within session"
echo " -d [session_name] Stop tracking session with session name. If"
echo " session_name is not passed then remove current session"
echo " -l List tracked sessions"
echo " -s <index> Switch to the session at the specified index in the"
echo " list of tracked sessions"
echo " -e Edit the sessions file"
echo " -h Display this help message"
}
remove() {
session_name="$1"
sed -i "/^$session_name/d" "$cachefile"
}
view() {
FZF_CMD="$(_getFZFCmd)"
entry="$(awk -v home="$HOME" -v bold="$(tput setaf 4)" -v sgr0="$(tput sgr0)" '{
split($0, parts, "=")
key = parts[1]
value = parts[2]
sub(home "/", "", value)
printf "%s%s%s %s\n", bold, key, sgr0, value
}' "$cachefile" | $FZF_CMD --ansi)"
name="$(echo "$entry" | cut -d ' ' -f 1)"
path="$HOME/$(echo "$entry" | rev | cut -d ' ' -f 1 | rev)"
{ [ -z "$name" ] || [ -z "$path" ]; } && exit 0
_switch "$name" "$path"
}
_getFZFCmd() {
! type fzf >/dev/null 2>&1 && echo "Harpoon depends on fzf" && exit 1
FZF_VERSION=$(fzf --version | cut -d ' ' -f1)
REQUIRED_VERSION="0.53.0"
version_gt() { [ "$(printf '%s\n' "$@" | sort -V | head -n1)" != "$1" ] || [ "$1" = "$2" ]; }
if version_gt "$FZF_VERSION" "$REQUIRED_VERSION"; then
echo "fzf --tmux 50%"
return 0
fi
if type fzf-tmux >/dev/null 2>&1; then
echo "fzf-tmux -p '50%,50%'"
return 0
fi
echo "fzf"
return 0
}
_getBookmark() {
extended=$1
base_info='#{session_name}=#{session_path}'
pane_info=':#{window_index}.#{pane_index}'
tmux display -p "$base_info$([ "$extended" = true ] && echo "$pane_info")"
}
_dedupe() {
tmpfile="$(mktemp)"
command cat -n "$cachefile" | sort -uk2 | sort -n | cut -f2- >"$tmpfile"
mv "$tmpfile" "$cachefile"
rm "$tmpfile"
}
replace() {
bookmark=$(_getBookmark "$1")
index=$2
linenumbers=$(wc -l <"$cachefile")
if [ "$linenumbers" -ge "$index" ]; then
escaped_bookmark=$(echo "$bookmark" | sed 's/\//\\\//g')
sed -i "${index}s/.*/$escaped_bookmark/" "$cachefile"
else
echo "$bookmark" >>"$cachefile"
fi
_dedupe
exec tmux display "Tracking session #{session_name} in index $index"
}
add() {
bookmark=$(_getBookmark "$1")
echo "$bookmark" >>"$cachefile"
_dedupe
exec tmux display 'Tracking session #{session_name}'
}
_switch() {
name="$1"
path="$2"
dirpath="${path%%:*}"
pane="${path#*:}"
[ "$dirpath" = "$pane" ] && pane=""
if ! sessions_has_match "$name=$dirpath"; then
if [ "$(uname)" = "Darwin" ]; then sedi="sed -i ''"; else sedi="sed -i"; fi
$sedi "s|^$name=.*|$name=$dirpath:1.1|" "$cachefile"
tmux new -ds "$name" -c "$dirpath"
fi
exec tmux switch-client -t "$name:$pane"
}
switch() {
index="$1"
count=1
while IFS='=' read -r name path; do
if [ "$count" = "$index" ]; then
_switch "$name" "$path"
fi
count=$((count + 1))
done <"$cachefile"
}
edit_file() { exec tmux popup -E "$EDITOR $cachefile"; }
sessions_has_match() { list_sessions | grep -wq "^$1"; }
list_sessions() { tmux ls -F '#{session_name}=#{session_path}'; }
bold() { printf "\033[1m%s\033[0m\n" "$*"; }
main() {
! [ -f "$cachefile" ] && touch "$cachefile"
while getopts ":haAr:R:d:ls:e" opt; do
case "$opt" in
h | :) help && exit 0 ;;
a) add false ;;
A) add true ;;
r) replace false "$OPTARG" ;;
R) replace true "$OPTARG" ;;
d) remove "$OPTARG" ;;
l) view ;;
s) switch "$OPTARG" ;;
e) edit_file ;;
\?) help && exit 1 ;;
esac
done
}
main "$@"