主要针对mobaXterm中分屏使用tmux,vim下的剪切板使用。内容整理的有些杂乱,有空再调整吧。

tmux剪切板设置

  • 使用场景
    win11的host中通过mobaXterm终端ssh连接virtualbox中的centos8。在centos中使用tmux进行terminal复用。
  • 需求
    在tmux中,需要能复制terminal的内容,能在tmux内部paste,且需要能复制到win host中的clipboard,以便可以在host中的notepad++等工具中paste供后续使用。
  • 分析
    mobaXterm等终端工具,通常提供基于鼠标选择的终端内容复制。如mobaXterm中默认通过鼠标选中终端内容后,即自动复制到host的clipboard中,通过单击鼠标滚轮即可实现paste。

    但在tmux下上述mobaXterm基于鼠标选择的复制方式受到限制,如通过ctl+b %进行分屏后,通过鼠标选择会选择到整个mobaXterm终端的内容,包含了多个pane的内容。即使tmux没有进行分屏,只有一个window的情况下,在vim下,通过vim的分屏,也会遇到类似的问题。

    实际上tmux提供了copy-mode,在copy-mode下,可以在当前pane中指定范围进行内容copy。copy的内容可以在tmux管理的window、pane、session中进行paste。也可以结合xclip等工具将copy的内容通过X11发送到X server(mobaXterm会运行X server),从而通过X server发送到host的clipboard。也有一些不通过X11实现的方法,如pbcopy。

    本文的解决方案即是基于tmux的copy-mode,在pane中选择指定的内容进行复制,并通过xclip连接X Server将复制内容发送到host的系统clipboard。

  • 环境信息

    . host: win11
    . hypervisor: virtualbox 7
    . vm: centos8
    . terminal: mobaXterm 20

X11-forwarding设置

如上,本文方案基于X11,首先需要保证对应的X11-forwarding是正常工作的,具体方法参考MobaXterm 中X11-forwarding问题。如下图,配置ok后,在mobaXterm登录ssh session的初始界面会显示X11-forwarding是ok的:
image.png

tmux设置

  • tmux默认的copy-mode使用方式
1. 进入copy-mode:ctl+b [ 
2. 通过上下左右移动选择你需要开始copy的位置,ctrl+space开始copy
3. 通过上下左右移动扩大你要选择的范围
4. copy到tmux buffer:ctl+w或者alt+w
5. 在目标pane、window中paste:ctl+b ]

mobaXterm中ctl+space默认被设置为执行macro,需要重新指定,以防止与tmux冲突。
image.png

  • 修改为vi的copy-mode
    比较习惯vi下面的操作模式,可以将tmux修改为vi下的copy-mode,并且通过xclip将tmux复制内容发送到host的clipboard。

    ~/.tmux.conf

    ## Use vim keybindings in copy mode
    #set-option -g mouse on
    setw -g mode-keys vi
    set-option -s set-clipboard off
    bind P paste-buffer
    
    bind-key -T copy-mode-vi v send-keys -X begin-selection
    # this not work
    # bind-key -T copy-mode-vi y send-keys -X rectangle-toggle
    bind-key -T copy-mode-vi y send -X copy-selection-and-cancel
    unbind -T copy-mode-vi Enter
    bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel 'xclip -se c -i'
    ##bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel 'xclip -se c -i'
  • vi的copy-mode用法
1. 进入copy-mode:ctl+b [ 
2. 通过hujk移动选择你需要开始copy的位置,v开始copy
3. 通过hujk移动扩大你要选择的范围
4/1. copy到tmux buffer(不拷贝到host的clipboard):y
4/2. copy到tmux buffer,并发送到host的clipboard:Enter 
5/1. 在目标pane、window中paste:ctl+b ]或者ctl+b P
5/2. 在host中paste:ctl+v 

tmux-copy-mode

linux安装xclip实现终端与剪贴板之间的通道

vi设置

  • 原理

    vim中有一个unnamed的register,y、yy、p等命令使用的即是这个register。而除了unnamed register,还有两个特殊的register,*和+。使用的时候通过"*和"+来指定使用。*y一般是selection register,即对应被选中的内容。通常Mac和windows中*和+都对应system clipboard。而此功能需要vim开启clipboard特性支持。利用它可以将vim复制的内容发送给host win11的系统clipboard。

    *也有一些不基于clipboard的实现,详细见下面连接。

  • 检查vim的clipboard功能是否开启
    如果没开启的话源码编译vim,打开clipboard支持。

    $ vim --version | grep clipboard
    -clipboard         +keymap            +printer           +vertsplit
    +eval              -mouse_jsbterm     -sun_workshop      -xterm_clipboard
  • 下载vim源码

    https://www.vim.org/download.php
    https://www.vim.org/git.php
    https://github.com/vim/vim
  • 安装X依赖

    yum install libX11-devel libXt-devel
  • 编译安装vim(开启clipboard功能)

    make distclean
    ./configure --with-features=huge --with-x --prefix=/usr/local
    make
    make install
  • 检查vim的clipboard功能是否开启

    ## bash的cache机制,可能导致vim不刷新
    [root@dw1-cn vim-9.0.1900]# hash -d vim
    [root@dw1-cn vim-9.0.1900]# vim --version | grep clipboard
    +clipboard         +keymap            +printer           +vertsplit
    +eval              -mouse_jsbterm     -sun_workshop      +xterm_clipboard
  • vim的clipboard用法 - copy-mode
1. 进入copy-mode:v 
2. 通过hujk确定copy的范围
3/1. 拷贝到unnamed register并退出copy-mode:y
3/2. 拷贝到+/* register并退出copy-mode:"+y或者"*y
4/1. 在目标buffer中paste:p
4/2. 在目标buffer中paste:"+p或者"*p
4/3. 在host中paste:ctl+v
  • vim的clipboard用法 - 非copy-mode
    以下常用复制命令,可以通过追加"+或者"*变更为复制到指定的clipboard

    yank 当前行:yy
    yank 4行:4yy
    yank word:yw
    yank直到下个X:yfX
    yank到行尾:y$
    yank到行首:y0/y^
    yank一段(yank a paragraph):yap
  • 设置默认使用"+

~/.vimrc
这种方式将匿名clipboard和*+clipboard合并,使用比较方便,不需要特别指定clipboard("*等方式)。但有些场景下会带来一些麻烦。如可能实现从系统中复制了一段文字,vim中编辑的时候,先dd删除了一段内容,又通过shift+insert粘贴system clipboard的内容,但是由于设置了默认使用了+clipboard,则dd的内容会覆盖掉之前复制的内容,导致粘贴的是dd的内容。还是推荐使用后面“推荐的方式”部分的方法。

:set clipboard=unnamedplus
  • 也可以如此bind
noremap <Leader>y "*y
noremap <Leader>p "*p
noremap <Leader>Y "+y
noremap <Leader>P "+p

黑暗森林
12 声望2 粉丝

弱小和无知不是生存的障碍,傲慢才是!


引用和评论

0 条评论