:ok_hand: Support for --remote and friends.
该软件包提供了一个名为nvr的可执行文件,用于解决以下情况:
- 在外壳程序中控制Neovim进程,例如在另一个终端窗口中打开文件。
- 在
:terminal内打开文件,而无需启动嵌套的Neovim进程。
安装
pip3 install neovim-remote
如果遇到权限错误或其他问题,如找不到nvr可执行文件,请阅读INSTALLATION.md。
原理
Neovim始终启动一个服务器。通过:echo v:servername获取其地址,或在启动时指定地址:nvim --listen /tmp/nvimsocket。
nvr(客户端)会使用通过--servername、$NVIM_LISTEN_ADDRESS(Neovim已弃用,但nvr仍支持)给出的任何地址,或者默认使用/tmp/nvimsocket。
如果没有找到目标地址,nvr将通过运行"nvim"启动新进程。可以通过设置$NVR_CMD更改命令。(这需要分叉操作,因此在Windows上可能无法工作。)
初学者指南
在一个shell中启动一个作为服务器的Neovim进程:
nvim --listen /tmp/nvimsocket
然后在另一个shell中:
# nvr默认使用/tmp/nvimsocket,所以这里没问题。
# 打开两个文件:
nvr --remote file1 file2
# 向当前缓冲区发送按键:
nvr --remote-send 'iabc<esc>'
# 进入插入模式,插入'abc',然后再回到正常模式。
# 评估VimL表达式,例如获取当前缓冲区:
nvr --remote-expr 'bufname("")'
README.md
点击这里查看所有nvr选项
$ nvr -h
使用方法: nvr [参数]
远程控制Neovim进程。
如果没有找到进程,将启动新的进程。
$ nvr --remote-send 'iabc<cr><esc>'
$ nvr --remote-expr 'map([1,2,3], "v:val + 1")'
所有未被选项消耗的参数将传递给--remote-silent:
$ nvr --remote-silent file1 file2
$ nvr file1 file2
所有--remote选项可以接受可选命令。
例外: --remote-expr, --remote-send。
$ nvr +10 file
$ nvr +'echomsg "foo" | echomsg "bar"' file
$ nvr --remote-tab-wait +'set bufhidden=delete' file
从终端缓冲区在新窗口中打开文件:
$ nvr -cc split file1 file2
从git中编辑提交信息:
$ git config --global core.editor 'nvr --remote-wait-silent'
可选参数:
-h, --help 显示此帮助消息并退出
--remote [<file> [<file> ...]]
使用:edit打开文件。如果没有找到进程,将抛出错误并启动新的进程。
--remote-wait [<file> [<file> ...]]
类似于--remote,但在所有由该选项打开的缓冲区被删除或进程退出之前阻塞。
--remote-silent [<file> [<file> ...]]
类似于--remote,但在找不到进程时不抛出错误。
--remote-wait-silent [<file> [<file> ...]]
结合了--remote-wait和--remote-silent。
--remote-tab [<file> [<file> ...]]
类似于--remote,但使用:tabedit。
--remote-tab-wait [<file> [<file> ...]]
类似于--remote-wait,但使用:tabedit。
--remote-tab-silent [<file> [<file> ...]]
类似于--remote-silent,但使用:tabedit。
--remote-tab-wait-silent [<file> [<file> ...]]
结合了--remote-wait-silent,但使用:tabedit。
--remote-send <keys> 发送按键。
--remote-expr <expr> 评估表达式并在shell中打印结果。
--servername <addr> 设置要使用的地址。这会覆盖默认的"/tmp/nvimsocket"和$NVIM_LISTEN_ADDRESS。
--serverlist 打印所有Neovim进程的TCPv4和Unix域套接字地址。
-cc <cmd> 在其他所有选项前执行命令。
-c <cmd> 在其他所有选项后执行命令。
-d 差异模式。对所有即将打开的缓冲区使用:diffthis。
-l 通过":wincmd p"切换到先前的窗口。
-o <file> [<file> ...]
通过":split"打开文件。
-O <file> [<file> ...]
通过":vsplit"打开文件。
-p <file> [<file> ...]
通过":tabedit"打开文件。
-q <errorfile> 读取错误文件到快速修复列表并显示第一条错误。
-s 阻止“没有找到服务器”消息。
-t <tag> 跳转到给定标记所在的文件和位置。
--nostart 如果没有找到进程,不要启动新的进程。
--version 显示nvr版本。
开发: https://github.com/mhinz/neovim-remote
快乐编码!
典型用例
-
在
:terminal内部打开文件,而不启动嵌套的Neovim进程。很简单!只需
nvr file。由于Neovim进程的所有子进程(包括
:terminal)总是设置$NVIM,nvr会默认使用这个地址,因此无需任何预先设置。我经常在相邻的两个窗口中工作。如果其中一个包含终端,我就可以使用
nvr -l foo在另一个窗口中打开文件。 -
无论您位于哪个终端,始终在同一Neovim进程中打开文件。
只需
nvr -s就会启动一个新的Neovim进程,服务器地址设为/tmp/nvimsocket。现在,无论你在哪个终端,
nvr file都会始终在那个Neovim进程中工作。这类似于Emacs中的emacsclient。 -
在插件中使用nvr。
一些插件依赖于Vim的
--remote系列选项。当Neovim将其大量手动代码外包给libuv时,不得不移除这些选项。不过,这些选项计划会重新添加回来。 -
将nvr用作Git编辑器。
如果通过
$VISUAL或$EDITOR设置了Neovim作为默认编辑器。在常规shell中运行
git commit会启动一个Neovim进程。但是,在:terminal缓冲区内,还会启动一个新的Neovim进程。现在你有一个Neovim嵌套在另一个Neovim里。如果不想这样,可以在你的vimrc中添加如下内容:
if has('nvim') let $GIT_EDITOR = 'nvr -cc split --remote-wait' endif这样,你可以为输入提交信息创建一个新的窗口,而不是嵌套的Neovim进程。确保保存完提交信息后删除缓冲区:
:w | bd。如果不喜欢使用
:w | bd,更喜欢用旧式的:wq(或:x),则在你的vimrc中添加以下内容:autocmd FileType gitcommit,gitrebase,gitconfig set bufhidden=delete也可以从常规shell中使用nvr:
$ git config --global core.editor 'nvr --remote-wait-silent' -
将nvr用作Git mergetool。
若要在
git difftool和git mergetool中使用nvr,请在你的gitconfig中添加以下内容:[diff] tool = nvr [difftool "nvr"] cmd = nvr -s -d $LOCAL $REMOTE [merge] tool = nvr [mergetool "nvr"] cmd = nvr -s -d $LOCAL $BASE $REMOTE $MERGED -c 'wincmd J | wincmd ='nvr -d是nvr -d -O的快捷方式,与vim -d类似,使用:vsplit打开缓冲区。如果你希望它们通过:split打开,使用nvr -d -o。当作为合并工具使用,并且打开了所有四个缓冲区时,光标将在包含$MERGED缓冲区的窗口中。我们通过
:wincmd J将其移动到底部,然后通过:wincmd =使所有窗口大小相等。 -
使用nvr进行脚本编程。
你可能会从中获得灵感这个Reddit线程。
演示
(点击GIF图片以全尺寸观看。)
从其他shell中使用nvr:
在:terminal内使用nvr:
常见问题解答
-
如何打开目录?
使用
:e /tmp会通过netrw插件打开一个目录视图。Netrw工作原理是挂钩到某些事件,例如此例中的BufEnter(查看:au FileExplorer了解所有事件)。不幸的是,Neovim的API不会自行触发任何自动命令,所以简单地
nvr /tmp无法工作。你可以这样绕过这个问题:$ nvr /tmp -c 'doautocmd BufEnter' -
从标准输入读取数据?
可以!比如
echo "foo\nbar" | nvr -o -和cat file | nvr --remote -就像你预期的那样工作。 -
退出代码?
如果你使用的是足够新的Neovim版本,nvr将会使用与其链接的nvim相同的退出代码。
例如,
nvr --remote-wait <file>后,在链接的nvim中执行:cquit会使nvr返回状态码1。 -
如何向所有等待的客户端发送消息?
当你用任何_等待_选项打开缓冲区时,该缓冲区会得到一个名为
b:nvr的变量。这个变量包含了一个列表,其中每个通道都是一个等待的nvr客户端。目前nvr仅理解
Exit消息。你可以用它一次性断开所有等待的nvr客户端连接:command! DisconnectClients \ if exists('b:nvr') \| for client in b:nvr \| silent! call rpcnotify(client, 'Exit', 1) \| endfor \| endif -
我能为bash/fish实现自动补全吗?
如果你想在bash中实现基础的自动补全,可以在你的.bashrc文件中源化这个脚本。
这也将会完成服务器名称的补全,与
--servername选项配合使用。如果你想要fish的自动补全,可以将这个文件添加到你的fish补全目录中。