1

По сути, я хочу создать оператор в сценарии 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 ответа2

1

:buffer откроет новый временный файл вместо текущего буфера. Вместо этого используйте writefile() . Это также может помочь с перерисовкой.

0

Я бы сказал, что существует более одного "правильного" способа сделать это, но ваши шаги могут быть упрощены, в зависимости от вашей реализации.

Прежде всего, вы можете напрямую записать диапазон текста в файл без необходимости:badd it. Если текст выделен визуально, просто нажмите:, и он автоматически вставит подходящий вам диапазон. Продолжайте вводить " w somefile ". Vim будет записывать в файл (создавая его при необходимости) только строки, указанные диапазоном для этого файла. Затем вы можете продолжить отправку текста в вашу внешнюю программу.

Во-вторых, вы даже можете записать текст непосредственно в канал, вместо записи в файл, а затем вызвать команду, используя « :w !command ". (Не забывайте свой диапазон, где это необходимо.)

Однако эти два параметра будут иметь проблемы с обработкой Vim полных строк, а не частичных, в диапазонах строки:-command, с которыми вы, вероятно, столкнетесь, плюс тот факт, что она не будет (легко) охватывать все ваши заявленные значения. и предполагаемые варианты использования, поэтому я бы сказал, что ваш оригинальный подход может быть более подходящим. Не видя вашей реальной реализации, я не могу придумать вескую причину, по которой он портит отображение Vim - у меня есть идеи, но их сложнее объяснить абстрактно, чем при наличии примеров для работы.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .