使用 neovim 导航在 tmux 中循环切换分割并保持全屏显示

使用 neovim 导航在 tmux 中循环切换分割并保持全屏显示

作为一名软件开发人员,我将 tmux 与 Neovim 结合使用(在 Debian 10 上)。

我遇到了以下两个问题,经过大量调查后仍然找不到适合我的解决方案:

  1. 我想无限循环切换分屏(就像浏览器上的标签一样)。假设我在 Neovim 上打开了 3 个垂直分屏,从最后一个分屏转到第一个分屏的唯一方法是向后循环,我想从最后一个分屏向右导航到第一个分屏。
  1. 当我“越过边界”时,tmux 会退出全屏,我想防止这种情况发生。所以我通常将 Neovim 放在顶部,占据屏幕的 70% 到 80%,并在底部放置一个终端(如上图所示),但有时我需要使用 tmux 进入全屏 Neovim。假设我在 Neovim 中打开了 2 个垂直分割,会发生什么情况是,当我在右侧分割中时,我不小心导航到右侧(由于右侧没有其他分割,我想像上面所述那样循环它们),tmux 会退出 Neovim 全屏,我不想发生这种情况,我只希望在我向下移动(即终端所在的位置)时发生这种情况,或者也许我只是使用我用于全屏的相同组合键(在我的情况下是 Ctrl-s + z)。

这是我的.tmux.conf:

# tmux display things in 256 colors
set -g default-terminal "screen-256color"

# Automatically renumber tmux windows
set -g renumber-windows on

# Unbind default prefix and set it to Ctrl+s
unbind C-b
set -g prefix C-s
bind C-s send-prefix

# Split window and fix path for tmux
bind / split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

# Pane movement shortcuts
# bind -n C-h select-pane -L
# bind -n C-j select-pane -D
# bind -n C-k select-pane -U
# bind -n C-l select-pane -R

# Smart pane switching with awareness of Vim splits.

# See: https://github.com/christoomey/vim-tmux-navigator
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'

tmux_version='$(tmux -V | sed -En "s/^tmux ([0-9]+(.[0-9]+)?).*/\1/p")'
if-shell -b '[ "$(echo "$tmux_version < 3.0" | bc)" = 1 ]' \
  "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\'  'select-pane -l'"
if-shell -b '[ "$(echo "$tmux_version >= 3.0" | bc)" = 1 ]' \
  "bind-key -n 'C-\\' if-shell \"$is_vim\" 'send-keys C-\\\\'  'select-pane -l'"

bind-key -T copy-mode-vi 'C-h' select-pane -L
bind-key -T copy-mode-vi 'C-j' select-pane -D
bind-key -T copy-mode-vi 'C-k' select-pane -U
bind-key -T copy-mode-vi 'C-l' select-pane -R
bind-key -T copy-mode-vi 'C-\' select-pane -l

# Resize pane shortcuts
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# Enable mouse support for switching panes/windows
setw -g mouse on

bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard'

set-option -g history-limit 10000

set-option -sg escape-time 10

答案1

如果您使用“christoomey/vim-tmux-navigator”,我认为这对您有用:

首要问题:

在我的系统中(在 Ubuntu 18.04 上使用 tmux 2.6,在 Debian Buster 上使用 tmux 2.7),我可以像您描述的那样循环浏览窗格。例如,如果我在最右侧的窗格中,并且我使用ctrl-l“向右”键,我最终会进入最左侧的窗格。将其放入您的 tmux conf 中应该可以解决问题:

# Smart pane switching with awareness of Vim splits.

# See: https://github.com/christoomey/vim-tmux-navigator
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

bind-key -n 'C-k' if-shell "$is_vim" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-j' if-shell "$is_vim" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'

由于我在 vim 中使用 fzf,并已设置ctrl+j/k为在列表中上下移动,因此我有一个额外的检查 ( is_fzf) 来触发该行为,而不是导航拆分。如果您想执行相同的操作,代码如下:

# Smart pane switching with awareness of Vim splits and fzf windows.

# See: https://github.com/christoomey/vim-tmux-navigator
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

# See: https://github.com/keeganlow/dotfiles/blob/master/.tmux.conf
is_fzf="ps -o state= -o comm= -t '#{pane_tty}' \
  | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?fzf$'"

bind-key -n 'C-k' if-shell "($is_vim || $is_fzf)" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-j' if-shell "($is_vim || $is_fzf)" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'

第二个问题:

在你的 vimrc 中,你可以使用:

let g:tmux_navigator_disable_when_zoomed = 1 

在 vim 中移动时不要脱离缩放。

编辑-我的整个.tmux.conf

# reload the tmux.conf and display a message to that effect
bind r source-file ~/.tmux.conf \; display "Reloaded .tmux.conf"

# source colorscheme
set -g default-terminal 'screen-256color'
# source-file ~/.tmux_light.conf

# remap prefix from CTRL-B to CTRL+Spacebar {{{
set -g prefix C-Space
unbind C-b
# }}}

# configure default limits/times {{{
# Set scrollback buffer to 10000
set -g history-limit 10000
# No delay for escape key press
set -sg escape-time 0
# When using repeatable commands (like resizing) repeat-time is the duration of
# the window (in milliseconds) for which a repeat can be made (default is 500)
set -g repeat-time 1000
# If I want to switch to another pane while in a fzf list, I can do prefix+q,
# then hit the number of the pane I want. Make those numbers last a bit longer.
# (I can always press escape to make them turn off immediately)
set -g display-panes-time 3000
# }}}

# pane and window indexing {{{
# Set the base index for windows to 1 instead of 0
set -g base-index 1
# Set the base index for panes to 1 instead of 0
set-window-option -g pane-base-index 1
# }}}

# pane navigation {{{
# allow the vim pluging 'tmux-plugins/vim-tmux-focus-events' to work
set -g focus-events on
# split panes using | and - {{{
%if "#{==:#{host},office}"
# ubuntu 20.04 
bind '\' split-window -h
%endif
%if "#{!=:#{host},office}"
# ubuntu 18.04 and debian buster
bind \ split-window -h
%endif

bind - split-window -v
unbind '"'
unbind %    
# }}}

# Pane resizing with prefix + H/J/K/L: {{{
bind -r H resize-pane -L 5
bind -r L resize-pane -R 5
bind -r K resize-pane -U 3
bind -r J resize-pane -D 3
# }}}
 
# Smart pane switching with awareness of Vim splits and fzf windows. {{{

# See: https://github.com/christoomey/vim-tmux-navigator
is_vim="ps -o state= -o comm= -t '#{pane_tty}' \
    | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'"

# See: https://github.com/keeganlow/dotfiles/blob/master/.tmux.conf
is_fzf="ps -o state= -o comm= -t '#{pane_tty}' \
  | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?fzf$'"

bind-key -n 'C-k' if-shell "($is_vim || $is_fzf)" 'send-keys C-k'  'select-pane -U'
bind-key -n 'C-j' if-shell "($is_vim || $is_fzf)" 'send-keys C-j'  'select-pane -D'
bind-key -n 'C-h' if-shell "$is_vim" 'send-keys C-h'  'select-pane -L'
bind-key -n 'C-l' if-shell "$is_vim" 'send-keys C-l'  'select-pane -R'

# go to last pane (like b# in vim)
bind '#' select-pane -l
# }}}
# }}}

# visually select and yank to system clipboard {{{
bind-key -T copy-mode-vi v send-keys -X begin-selection
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xclip -sel clip -i'
# like visual block mode
bind-key -T copy-mode-vi r send-keys -X rectangle-toggle
# I think I might overwrite the lower case p for 'previous window', since I
# can just use next/numbers to swtich
bind P paste-buffer
# }}}

相关内容