我按以下方式一起使用 Vim (8.0) 和 tmux (2.3):在 tmux 会话中,我有一个窗口分为 2 个窗格,一个窗格有一些在 Vim 中打开的文本文件,另一个窗格有一些我要使用的程序想要发送文本行。典型的用例是将 Python 脚本中的行发送到在另一个窗格中运行的 IPython 会话。
我通过使用 python 的 Vim 脚本执行此操作,代码片段示例(假设目标 tmux 窗格为 0):
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
Run Code Online (Sandbox Code Playgroud)
这工作得很好,除了当cmd有一些必须转义的字符时,比如%、#、$等。cmd变量是从 Vim 打开的文本文件的当前行读取的,所以我可以做类似的事情cmd = cmd.replace('%', '\%'),但这有2个缺点:首先,我不知道所有必须转义的vim字符,所以到目前为止一直在尝试和错误,其次,字符"没有正确转义 - 即在Vim获取的字符串中,"即使我这样做了,它也会消失cmd = cmd.replace('"', '\"')。那么,有没有一种通用的方法告诉 Vim 不要解释任何东西,只获取原始字符串并按原样发送?如果不是,为什么没有"正确转义?
您正在寻找该shellescape()功能。如果您使用:!Vim 命令,则{special}参数需要为 1。
silent execute '!tmux send-keys -t 0 -l ' . shellescape(cmd, 1)
Run Code Online (Sandbox Code Playgroud)
但由于您对(显示)shell 输出不感兴趣,并且不需要与启动的脚本交互,所以我会切换到:!较低级别的system()命令。
call system('tmux send-keys -t 0 -l ' . shellescape(cmd))
Run Code Online (Sandbox Code Playgroud)
使用Python(而不是纯Vimscript)没有任何好处(至少在你问题中的小片段中)。相反,如果您将 Pythoncmd变量嵌入到 Vimscript 表达式中,现在您还需要一个 Python 函数来将值转义为 Vimscript 字符串(类似于'%s'" % str(cmd).replace("'", "''")))。或者,您可以在 Vim 变量中维护该值,并通过 Python 从 Python 访问它vim.vars。