forked from sunaku/tmux-navigate
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tmux-navigate.tmux
executable file
·112 lines (93 loc) · 3.19 KB
/
tmux-navigate.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
#!/bin/sh
#
# Intelligently navigate tmux panes and Vim splits using the same keys.
# This also supports SSH tunnels where Vim is running on a remote host.
#
# +-------------+------------+-----------------------------+
# | inside Vim? | is Zoomed? | Action taken by key binding |
# +-------------+------------+-----------------------------+
# | No | No | Focus directional tmux pane |
# | No | Yes | Nothing: ignore key binding |
# | Yes | No | Seamlessly focus Vim / tmux |
# | Yes | Yes | Focus directional Vim split |
# +-------------+------------+-----------------------------+
#
# See https://sunaku.github.io/tmux-select-pane.html for documentation.
get_tmux_option() { tmux show-option -gqv "$@" | grep . ;}
navigate=$(sed '1,/^exit #.*$/d; s/^ *#.*//; /^$/d' "$0")
navigate_left=" $navigate L 'tmux select-pane -L' 'tmux send-keys C-w h'"
navigate_down=" $navigate D 'tmux select-pane -D' 'tmux send-keys C-w j'"
navigate_up=" $navigate U 'tmux select-pane -U' 'tmux send-keys C-w k'"
navigate_right="$navigate R 'tmux select-pane -R' 'tmux send-keys C-w l'"
navigate_back=" $navigate l 'tmux select-pane -l || tmux select-pane -t1'\
'tmux send-keys C-w p' \
'pane_is_zoomed' "
for direction in left down up right back; do
option="@navigate-$direction"
handler="navigate_$direction"
if key=$(get_tmux_option "$option"); then
eval "action=\$$handler" # resolve handler variable
tmux bind-key $key run-shell -b ": $option; $action"
fi
done
exit #------------------------------------------------------------------------
# interpolate tmux values ONCE at "compile time"
# (this is the reason for the double ## escapes)
pane_title="#{q:pane_title}"
pane_current_command="#{q:pane_current_command}"
window_zoomed_flag=#{window_zoomed_flag}
pane_is_zoomed() {
test $window_zoomed_flag -eq 1
}
command_is_vim() {
case "${1%% *}" in
(vi|?vi|vim*|?vim*|view|?view|vi??*)
true
;;
(*)
false
;;
esac
}
pane_contains_vim() {
command_is_vim "$pane_current_command" ||
command_is_vim "$pane_title"
}
pane_contains_neovim_terminal() {
case "$pane_title" in
(nvim?term://*)
true
;;
(*)
false
;;
esac
}
navigate() {
tmux_navigation_direction=$1
tmux_navigation_command=$2
vim_navigation_command=$3
vim_navigation_only_if=${4:-true}
# try navigating Vim
if pane_contains_vim && eval "$vim_navigation_only_if"; then
# parse navigable directions from Vim's title
vim_navigable_directions=${pane_title####* }
# if desired direction is navigable in Vim...
case "l$vim_navigable_directions" in (*$tmux_navigation_direction*)
# leave insert mode in NeoVim terminal
if pane_contains_neovim_terminal; then
tmux send-keys C-\\ C-n
fi
# navigate Vim and don't fall through
eval "$vim_navigation_command"
return
;;
esac
# otherwise fall through into tmux navigation
fi
# try navigating tmux
if ! pane_is_zoomed; then
eval "$tmux_navigation_command"
fi
}
navigate