Пользовательский g: буфер обмена приводит к тому, что `p` всегда вставляется в одну строку

Aug 20 2020

Задний план

Я использую wayland и neovim, и при вставке внешнего текста он добавлялся ^Mв конец каждой строки. Это известный «баг» (https://github.com/neovim/neovim/issues/10223) и существует обходной путь: использование sed для обрезки ^M:

let g:clipboard = {
            \   'name': 'WL-Clipboard with ^M Trim',
            \   'copy': {
            \      '+': 'wl-copy --foreground --type text/plain',
            \      '*': 'wl-copy --foreground --type text/plain --primary',
            \    },
            \   'paste': {
            \      '+': {-> systemlist('wl-paste --no-newline | sed -e "s/\r$//"')}, \ '*': {-> systemlist('wl-paste --no-newline --primary | sed -e "s/\r$//"')},
            \   },
            \   'cache_enabled': 1,
            \ }

В wl-pasteмоей системе Neovim по умолчанию используется , если g:clipboardне установлен.

Проблема

При наличии обходного пути neovim не вставляет построчные копии в новую строку.

  • Ожидаемое поведение : перейти к строке -> нажать Y-> перейти к середине другой строки -> нажать p-> скопированная строка вставляется в новую строку. Вот что происходит, когда установлено « нет» g:clipboard .

  • Наблюдаемое поведение : перейти к строке -> нажать Y-> перейти к середине другой строки -> нажать p-> скопированная строка вставляется в текущую строку. Вот что происходит при g:clipboardустановке.

При просмотре содержимого буфера обмена Wayland ( wl-paste --no-newline | cat -A) они одинаковы. Оба заканчиваются символом LF.

Вопрос:

Почему это? Что делает neovim, чтобы различать вставку в новую строку, и почему neovim не вставляет в новую строку, когда есть кастом g:clipboard?

Ответы

3 Matt Aug 20 2020 at 01:40

По умолчанию systemlist()не сохраняет последний символ новой строки (т.е. удаляет последний элемент «пустая строка» из результирующего списка). Это заставляет Neovim думать, что содержимое буфера обмена имеет тип char, а не line.

Следовательно, вместо этого вы должны сделать следующее (см. :h systemlist(), Обратите внимание, что версия Neovim отличается от версии Vim):

{-> systemlist('wl-paste...', '', 1)}

Другой вариант, если вы используете исключительно версию Neovim с графическим интерфейсом пользователя, вы можете просто отправить запрос RPC в ваше приложение с графическим интерфейсом, которое может обслуживать его независимо от платформы (через Qt, Gtk и т. .).

Например, nvim-qt поставляется со стандартным плагином nvim_gui_shim, который предоставляет GuiClipboard()функции. Таким образом, выполнение просто :call GuiClipboard()автоматически установит для вас "custom", в g:clipboardкотором уже есть те rpcrequest()и rpcnotify()вызовы.

Однако, помимо того, что это не будет работать под простой консолью nvim, я обнаружил еще одну неприятную проблему: по крайней мере, в nvim-qt требуется, чтобы пользовательский интерфейс был введен и полностью подготовлен. И поэтому может быть неудобно настраивать его при запуске Neovim. Конечно, g:clipboardвместо этого вы можете предоставить свои собственные вызовы RPC (примечание: параметры RPC могут различаться в разных интерфейсах графического интерфейса; также некоторые приложения могут вообще не реализовывать такие запросы).

Еще один вариант - реализовать доступ к буферу обмена самостоятельно. Вот мой собственный поставщик буфера обмена Neovim, который может делать это без внешних зависимостей. Однако до сих пор я реализовал только версию Xlib, поэтому для Wayland нет собственного модуля.