Skip to content

Commit 3e51131

Browse files
committed
refactor: fully rewrite opening logic
- Iterate over all nvim sockets and find their associated panes. Traversing from sockets -> ppid (nvim client) -> ppid (shell/pane), instead of iterating through all panes - If there is one instance of nvim in the current window open there, otherwise display a menu that allows the user to select a pane containing nvim and open the file there. The menu can be styled with options in tmux conf. - If no nvim is found, the logic is the same and will just open in the current pane.
1 parent 0007f9e commit 3e51131

File tree

4 files changed

+61
-50
lines changed

4 files changed

+61
-50
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ Available configuration options to put in your `.tmux.conf`
3333
|Config |Description | Example
3434
|--- |--- |---
3535
|`set -g @ton-open-strategy ":e"` | Command for opening a file | `:e` or `:tabnew`
36-
36+
|`set -g @ton-menu-style` | Set style of display-menu for picking a pane | See `man tmux` STYLES
37+
|`set -g @ton-menu-selected-style` | Set style of display-menu selection for picking a pane | See `man tmux` STYLES
3738

3839
## Usage
3940

@@ -50,6 +51,10 @@ $ ton file.txt # optionally add :[line]:[col] to the end, i.e file.txt:40:5
5051
# Opens file.txt in nvim pane
5152
```
5253

54+
If you have more than one Neovim instance running in a tmux window, you will be
55+
prompted with a tmux display-menu that will allow you to select where to open
56+
the file.
57+
5358
#### Caveat
5459

5560
Upon launch of a fresh tmux session, the script will not be in the first pane

scripts/ton

+40-49
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ source "$CURRENT_DIR/variables.sh"
88
source "$CURRENT_DIR/helpers.sh"
99

1010
OPEN_STRATEGY="$(get_tmux_option "$open_strategy" ":e")"
11+
MENU_STYLE="$(get_tmux_option "$menu_style")"
12+
MENU_SELECTED_STYLE="$(get_tmux_option "$menu_selected_style")"
1113

1214
# Check pipe from stdin or parameter
1315
FPATH=${STDIN:-$1}
@@ -30,60 +32,49 @@ LINE=${a[1]:-0}
3032
COLUMN=${a[2]:-0}
3133

3234
# Get all nvim listening sockets (default location)
33-
IFS=':' read -r -a LISTEN_SOCKS <<<"$(ls "${XDG_RUNTIME_DIR:-${TMPDIR}nvim.${USER}}"/**/nvim.*.0 2>/dev/null | tr '\n' ':')"
34-
IFS=$OIFS
35-
36-
# Match child process with nvim sock, since process is within
37-
# e.g `/run/user/1000/nvim.1624238.0` -- nvim process is 1624238
38-
IFS=':' read -r -a panes <<<"$(tmux list-panes -a -F '#{window_index} #{pane_index} #{pane_pid}' | tr '\n' ':')"
39-
IFS=$OIFS
35+
readarray -t LISTEN_SOCKS < <(ls "${XDG_RUNTIME_DIR:-${TMPDIR}nvim.${USER}}"/**/nvim.*.0 2>/dev/null)
4036

41-
CURRENT_WINDOW_ID=$(tmux display-message -p '#{window_index}')
42-
43-
# args:
44-
# socket
45-
# win_id
46-
# pane_id
47-
remote_open() {
48-
nvim --server "$1" --remote-send "<esc>$OPEN_STRATEGY $FILE<cr>"
49-
nvim --server "$1" --remote-send "<esc>:call cursor($LINE, $COLUMN)<cr>"
50-
tmux selectw -t "$2" && tmux selectp -t "$3"
51-
exit 0
52-
}
37+
CURRENT_WINDOW_INDEX=$(tmux display-message -p '#{window_index}')
5338

54-
for pane in "${panes[@]}"; do
55-
IFS=' ' pane_ids=($pane)
56-
IFS=$OIFS
39+
MENU_ARGS=()
40+
SOCK_COUNT=${#LISTEN_SOCKS[@]}
41+
SOCK_INDEX=1
42+
for sock in "${LISTEN_SOCKS[@]}"; do
43+
# extract pid from socket path
44+
server_pid=$(echo "$sock" | cut -d'.' -f2)
45+
# process id of server's parent, which is the nvim client
46+
client_pid=$(ps -o ppid= -p "$server_pid" | tr -d ' ')
47+
# process id of tmux pane that contains the nvim client
48+
pane_pid=$(ps -o ppid= -p "$client_pid" | tr -d ' ')
5749

58-
win_id=${pane_ids[0]}
59-
pane_id=${pane_ids[1]}
60-
pid=${pane_ids[2]}
50+
# tmux ids for the nvim client pane
51+
readarray -d ' ' -t ids < <(tmux list-panes -a -f "#{==:#{pane_pid},$pane_pid}" -F "#{window_index} #{window_name} #{pane_index}")
52+
window_index=${ids[0]}
53+
window_name=${ids[1]}
54+
pane_index=${ids[2]}
6155

62-
# Get pid of nvim process
63-
cpid=$(pgrep -P "$pid" nvim)
64-
ppid=0
65-
if [ $cpid ]; then
66-
# Get pid of nvim parent RPC process (--embed)
67-
ppid=$(pgrep -P "$cpid" nvim)
56+
c1="nvim --server $sock --remote-send \"<esc>$OPEN_STRATEGY $FILE<cr>\""
57+
c2="nvim --server $sock --remote-send \"<esc>:call cursor($LINE, $COLUMN)<cr>\""
58+
c3="tmux selectw -t $window_index && tmux selectp -t $pane_index"
59+
remote_open="$c1 && $c2 && $c3"
60+
if [[ $window_index == "$CURRENT_WINDOW_INDEX" ]] && [[ $SOCK_COUNT == 1 ]]; then
61+
# we found a nvim running in our window, escape hatch
62+
eval $remote_open
63+
exit 0
64+
else
65+
# store this nvim instance for selection
66+
MENU_ARGS+=("$window_name: pane $pane_index" "$SOCK_INDEX" "run '$remote_open'")
6867
fi
69-
70-
for sock in "${LISTEN_SOCKS[@]}"; do
71-
# Check if the nvim process associated with the socket is the parent id
72-
# Prioritize instances running in the current window, but fallback to first found instance
73-
if [[ $sock == *nvim.$ppid.* ]] && [[ $win_id == $CURRENT_WINDOW_ID ]]; then
74-
remote_open $sock $win_id $pane_id
75-
elif [[ $sock == *nvim.$ppid.* ]] && [[ ! $SOCK ]]; then
76-
SOCK=$sock
77-
WIN_ID=$win_id
78-
PANE_ID=$pane_id
79-
fi
80-
done
68+
SOCK_INDEX=$(($SOCK_INDEX + 1))
8169
done
8270

83-
if [[ $SOCK ]]; then
84-
remote_open $SOCK $WIN_ID $PANE_ID
71+
if [[ ${MENU_ARGS[0]} ]]; then
72+
# open menu for selection
73+
tmux menu -s "$MENU_STYLE" -H "$MENU_SELECTED_STYLE" -T "tmux-open-nvim: $FILE" "${MENU_ARGS[@]}"
74+
exit 0
75+
else
76+
# No remote nvim, so just open in current pane
77+
tmux send-keys "nvim -c \"call cursor($LINE, $COLUMN)\" $FILE"
78+
tmux send-keys "C-m"
79+
exit 0
8580
fi
86-
87-
# No remote nvim, so just open in current pane
88-
tmux send-keys "nvim -c \"call cursor($LINE, $COLUMN)\" $FILE"
89-
tmux send-keys "C-m"

scripts/variables.sh

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@
22
# ex. :e or :tabnew
33
open_strategy="@ton-open-strategy"
44
open_strategy_default=":e"
5+
6+
menu_style="@ton-menu-style"
7+
menu_selected_style="@ton-menu-selected-style"

tmux_open_nvim.tmux

+12
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,20 @@ set_open_strategy() {
1717
tmux set-option -gq "$open_strategy" "$strategy"
1818
}
1919

20+
set_menu_style() {
21+
local style=$(get_tmux_option "$menu_style")
22+
tmux set-option -gq "$open_strategy" "$style"
23+
}
24+
25+
set_menu_selected_style() {
26+
local style=$(get_tmux_option "$menu_selected_style")
27+
tmux set-option -gq "$menu_selected_style" "$style"
28+
}
29+
2030
main() {
2131
set_open_strategy
32+
set_menu_style
33+
set_menu_selected_style
2234
path_add "$SCRIPT_DIR"
2335
}
2436
main

0 commit comments

Comments
 (0)