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