Essentially I want to create an operator in a Vim script that sends selected text to an external (Python) script. It should behave like one would normally expect an operator to, whether the text is selected in Visual mode or using a movement. This has proven more difficult for me than I expected, and one fun limitation is that the operator needs to work on Vim versions from 6.3 to 7.0. I am using the console version of Vim, rather than GVim, as it's easier for my personal workflow.
My motivation: I want to copy text to the system clipboard from Vim (without using the mouse), so that I can paste it in another terminal tab. Frustratingly, on the systems I work with, Vim has been compiled without clipboard support, so the "+ and "* registers won't help me. It's easy enough to slap together a quick Python script to put arbitrary text into the clipboard, but the trouble is passing the text to the script from Vim.
What I've tried: My first thought was to yank the text, create a new buffer, put the text in there, save it as a file in /tmp, and execute a command like "cat /tmp/stuff | clipboard.py" from the function. More specifically: I used let scratchFile = system("mktemp")
to create a temp file, badd
to add the file as a buffer, and buffer
to switch to the new buffer. I then put the text I'm operating on in the buffer, write it, then do silent execute "!cat % | clipboard.py"
followed by bd
to get rid of the buffer. This doesn't really work. (It screws up the way Vim draws the contents of the original file on the screen, such that I have to highlight the file in Visual mode to get the text to appear again. :redraw
does not fix the problem.)
Is there a better approach to solving this problem?
Edit to add my script-in-progress:
nnoremap <C-y> :set operatorfunc=<SID>CopyClipboard<cr>g@
vnoremap <C-y> :<c-u>call <SID>CopyClipboard(visualmode())<cr>
function! s:CopyClipboard(type)
let saved_register = @@
if a:type ==? 'v'
normal! `<v`>y
let scratchFile = system("mktemp")
execute "badd " . scratchFile
execute "buffer " . scratchFile
normal! P
write
silent execute "!cat % | clipboard.py"
execute "bd! " . scratchFile
elseif a:type ==# 'char'
normal! `[v`]y
else
return
endif
let @@ = saved_register
endfunction