Reputation: 9645
I am using Vim (8.0) and tmux (2.3) together in the following way: In a tmux session I have a window split to 2 panes, one pane has some text file open in Vim, the other pane has some program to which I want to send lines of text. A typical use case is sending lines from a Python script to IPython session running in the other pane.
I am doing this by a Vim script which uses python, code snippet example (assuming the target tmux pane is 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
This works well, except for when cmd
has some characters which has to be escaped, like %
, #
, $
, etc. The cmd
variable is read from the current line in the text file opened in Vim, so I can do something like cmd = cmd.replace('%', '\%')
etc., but this has 2 disadvantages: first, I don't know all the vim characters which have to be escaped, so it has been trial and error up until now, and second, the characters "
is not escaped properly - that is in the string Vim gets, the "
just disappears, even if I do cmd = cmd.replace('"', '\"')
.
So, is there a general way to tell Vim to not interpret anything, just get a raw string and send it as is? If not, why is the "
not escaped properly?
Upvotes: 5
Views: 856
Reputation: 172608
You're looking for the shellescape()
function. If you use the :!
Vim command, the {special}
argument needs to be 1.
silent execute '!tmux send-keys -t 0 -l ' . shellescape(cmd, 1)
But as you're not interested in (displaying) the shell output, and do not need to interact with the launched script, I would switch from :!
to the lower-level system()
command.
call system('tmux send-keys -t 0 -l ' . shellescape(cmd))
The use of Python (instead of pure Vimscript) doesn't have any benefits (at least in the small snippet in your question). Instead, if you embed the Python cmd
variable in a Vimscript expression, now you also need a Python function to escape the value as a Vimscript string (something like '%s'" % str(cmd).replace("'", "''"))
). Alternatively, you could maintain the value in a Vim variable, and access it from Python via vim.vars
.
Upvotes: 4