将文本字符串从 python-vim 脚本发送到 tmux 窗格

Send literal string from python-vim script to a tmux pane

我通过以下方式一起使用 Vim (8.0) 和 tmux (2.3):在 tmux 会话中,我将一个窗口拆分为 2 个窗格,一个窗格在 Vim 中打开了一些文本文件,另一个窗格有一些程序我想向其发送文本行。一个典型的用例是将 Python 脚本中的行发送到在另一个窗格中运行的 IPython 会话。

我正在通过一个使用 python 的 Vim 脚本执行此操作,代码片段示例(假设目标 tmux 窗格为 0):

1
2
3
4
5
6
py import vim
python << endpython
cmd ="print 1+2"
vim_cmd ="silent !tmux send-keys -t 0 -l "" + cmd +""" # -l for literal
vim.command(vim_cmd)
endpython

这很好用,除了当 cmd 有一些必须转义的字符时,例如 %#$ 等。cmd 变量是从当前行中读取的文本文件在 Vim 中打开,所以我可以做类似 cmd = cmd.replace('%', '\\%') 之类的操作,但这有两个缺点:首先,我不知道必须转义的所有 vim 字符,所以一直在反复试验到现在为止,第二,字符 " 没有正确转义 - 也就是说,在 Vim 得到的字符串中,即使我使用 cmd = cmd.replace('"', '"')" 也会消失。
那么,有没有一种通用的方法来告诉 Vim 不解释任何内容,只获取一个原始字符串并按原样发送?如果不是,为什么 " 没有正确转义?


Vimscript

您正在寻找 shellescape() 函数。如果你使用 :! Vim 命令,{special} 参数需要为 1.

1
silent execute '!tmux send-keys -t 0 -l ' . shellescape(cmd, 1)

但是由于您对(显示)shell 输出不感兴趣,并且不需要与启动的脚本进行交互,所以我将从 :! 切换到较低级别的 system() 命令。

1
call system('tmux send-keys -t 0 -l ' . shellescape(cmd))

Python

使用 Python(而不是纯 Vimscript)没有任何好处(至少在您问题中的小片段中)。相反,如果你将 Python cmd 变量嵌入到 Vimscript 表达式中,现在你还需要一个 Python 函数来将值转义为 Vimscript 字符串(类似于 '%s'" % str(cmd).replace("'","''")))。或者,您可以将值保存在 Vim 变量中,并通过 Python 通过 vim.vars.

访问它