Как передать содержимое регистра Vim во внешний скрипт?
По сути, я хочу создать оператор в сценарии Vim, который отправляет выделенный текст во внешний (Python) сценарий. Он должен вести себя так, как обычно ожидал бы оператор, независимо от того, выбран ли текст в визуальном режиме или используется движение. Для меня это оказалось сложнее, чем я ожидал, и одно забавное ограничение заключается в том, что оператору необходимо работать с версиями Vim с 6.3 до 7.0. Я использую консольную версию Vim, а не GVim, поскольку это облегчает мой личный рабочий процесс.
Моя мотивация: я хочу скопировать текст в системный буфер обмена из Vim (без использования мыши), чтобы я мог вставить его в другую вкладку терминала. К сожалению, в системах, с которыми я работаю, Vim был скомпилирован без поддержки буфера обмена, поэтому регистры "+" и "*" мне не помогут. Достаточно просто собрать быстрый скрипт Python, чтобы поместить произвольный текст в буфер обмена, но проблема заключается в передаче текста в скрипт из Vim.
То, что я пробовал: моей первой мыслью было восстановить текст, создать новый буфер, поместить туда текст, сохранить его в виде файла в / tmp и выполнить команду наподобие "cat / tmp / stuff | clipboard.py "из функции. Более конкретно: я использовал let scratchFile = system("mktemp")
создать временный файл, badd
добавить файл в качестве буфера, и buffer
переключиться на новый буфер. Затем я помещаю текст, над которым я работаю, в буфер, пишу его, затем делаю silent execute "!cat % | clipboard.py"
с последующим bd
избавиться от буфера. Это на самом деле не работает. (Он искажает способ, которым Vim рисует содержимое исходного файла на экране, так что мне нужно выделить файл в визуальном режиме, чтобы текст снова появился. :redraw
не решает проблему.)
Есть ли лучший подход к решению этой проблемы?
Изменить, чтобы добавить мой скрипт в процессе:
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
2 ответа
:buffer
откроет новый временный файл вместо текущего буфера. использование writefile()
функция вместо Это также может помочь с перерисовкой.
Я бы сказал, что есть более одного "правильного" способа сделать это, но ваши шаги могут быть упрощены, в зависимости от вашей реализации.
Прежде всего, вы можете напрямую записать диапазон текста в файл без необходимости:badd it. Если у вас есть текст, выбранный визуально, просто нажмите:, и он автоматически вставит соответствующий диапазон для вас. Продолжайте печататьw somefile
Msgstr "Vim запишет в файл (создавая его при необходимости) только строки, указанные диапазоном для этого файла. Затем вы можете продолжить отправку текста в вашу внешнюю программу.
Во-вторых, вы можете даже написать текст непосредственно в канал, вместо записи в файл и затем вызвать команду, используя ":w !command
". (Не забывайте свой диапазон, где это необходимо.)
Однако эти два параметра будут иметь проблемы с обработкой Vim полных строк, а не частичных, в диапазонах строки:-command, с которыми вы, вероятно, столкнетесь, плюс тот факт, что она не будет (легко) охватывать все ваши заявленные значения. и предполагаемые варианты использования, поэтому я бы сказал, что ваш оригинальный подход может быть более подходящим. Не видя вашей реальной реализации, я не могу придумать вескую причину, по которой он портит отображение Vim - у меня есть идеи, но их сложнее объяснить абстрактно, чем если бы были примеры для работы.