forked from b0o/tmux-conf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
navi.tmux
executable file
·143 lines (130 loc) · 2.87 KB
/
navi.tmux
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
#!/usr/bin/env bash
# navi.tmux: faster navigation between tmux and vim
# Copyright 2024 Maddison Hellstrom <github.com/b0o>, MIT License.
set -euo pipefail
# TODO: Support setting these using tmux options like @navi-interval, @navi-pattern
declare pattern="g?(view|n?vim?x?|ssh)(diff)?"
declare interval="0.5"
declare -A state=()
function usage() {
cat <<EOF
Usage: navi.tmux [-h] [-f] [-k] [-s] [-i interval] [-p pattern]
Options:
-h Show this help message
-f Run in the foreground
-k Kill the running instance
-s Get the status of the running instance
-i Set the interval in seconds (default: "0.5")
-p Set the pattern to match (default: "$pattern")
EOF
}
function get_instance() {
local -i instance_pid
instance_pid="$(tmux show-options -gv "@navi-pid" 2>/dev/null)"
if [[ "$instance_pid" -gt 0 ]] && ps "$instance_pid" &>/dev/null; then
echo "$instance_pid"
return 0
fi
return 1
}
function kill_instance() {
local -i instance_pid
if instance_pid="$(get_instance)"; then
kill "$instance_pid"
echo "navi: killed $instance_pid"
return 0
fi
echo "navi: not running"
return 1
}
function get_status() {
local -i instance_pid
if instance_pid="$(get_instance)"; then
echo "running: $instance_pid"
return 0
fi
echo "not running"
return 1
}
function tick() {
local panes procs
panes="$(tmux list-panes -aF "#{pane_id}:#{pane_tty}")"
procs="$(ps a -ostate=,tty=,comm=)"
while read -r pane; do
local pane_id tty
pane_id="${pane%%:*}"
tty="${pane#*:}"
tty="${tty#/dev/}"
if [[ -z "$tty" ]]; then
continue
fi
local -i val
if grep -iqE "^[^TXZ ]+ ${tty} +(\S+/)?${pattern}\$" <<<"$procs"; then
val=1
else
val=0
fi
if [[ -z "${state["$pane_id"]:-}" || "${state["$pane_id"]}" -ne "$val" ]]; then
state["$pane_id"]=$val
echo tmux set-option -pt "$pane_id" "@navi-state" "$val"
tmux set-option -pt "$pane_id" "@navi-state" "$val"
fi
done <<<"$panes"
}
function loop() {
while true; do
tick
sleep "$interval"
done
}
function onexit() {
tmux set-option -gu "@navi-pid" &
}
function main() {
if ! [[ "${1:-}" =~ ^-[hfks]$ ]]; then
if get_instance &>/dev/null; then
exit 0
fi
"${BASH_SOURCE[0]}" -f "$@" &>/dev/null &
disown
exit 0
fi
local opt OPTARG
local -i OPTIND
while getopts ":hfksi:p:" opt "$@"; do
case "$opt" in
h)
usage
return
;;
f)
# Silently ignore -f
;;
k)
kill_instance
return
;;
s)
get_status
return
;;
i)
interval="$OPTARG"
;;
p)
pattern="$OPTARG"
;;
\?)
return 1
;;
esac
done
shift $((OPTIND - 1))
if get_instance &>/dev/null; then
return 1
fi
tmux set-option -g "@navi-pid" $$
loop
trap "onexit" EXIT
}
main "$@"