Я хотел бы заменить части одной строки результатом выделения, передаваемого в команду.

Например:

echo "hello $(echo "world" | base64)" | vim -

Это откроет буфер с hello d29ybGQK в нем. Теперь нажмите wvw, чтобы визуально выбрать d29ybGQK.

Затем я попытался :!base64 -d и ожидал, что буфер будет содержать hello world, чего не произошло. Действительно, вся строка была передана в команду, и вся строка была заменена.

Можно ли заменить только визуальное выделение и передать в команду только это выделение?

Я также попытался c<c-r>=system('base64 -d'), но это не отправило визуальное выделение на стандартный ввод команды.

vim
3
Benoit Duffez 24 Сен 2018 в 10:41

2 ответа

Лучший ответ

Фильтрация с помощью ! всегда выполняется по строкам. Ваше решение с c и Регистр выражений - отличный способ решить эту проблему. Ты только забыл для передачи ввода в system(), который является его вторым необязательным аргументом.

Поскольку вы только что изменили выделенный текст, он вошел в регистр " автоматически. Все, что вам нужно сделать, это взять его и передать система с getreg():

c<C-R>=system('base64 -D', getreg('"'))

Обратите внимание, что base64 может отображать перевод строки в конце. Если вы хотите удалить либо оберните все это в trim(), новую функцию в Vim 8, либо используйте [:-2]:

c<C-R>=trim(system('base64 -D', getreg('"')))
c<C-R>=system('base64 -D', getreg('"'))[:-2]

Это сокращение от [0:-2], означающее захватить все из символа От 0 до второго конца в результирующей строке.

Рассмотрите возможность создания визуальной карты, если вы часто ее используете:

vnoremap <leader>d c<C-R>=system('base64 -D', getreg('"'))[:-2]<CR>
8
sidyll 24 Сен 2018 в 14:22

По историческим причинам команды Ex по своей сути основаны на строках; Достопочтенный vi тоже еще не имел визуального режима. Это ограничение включает фильтрацию с помощью внешней команды с :range!; он всегда будет фильтровать полные строки.

Ручное решение

Для простого ввода, как в вашем примере, вероятно, проще всего временно разделить строку, отфильтровать и затем собрать заново. Например:

:substitute/ /\r/ | execute '.!base64 -d' | -1join

Плагин решение

Для универсального решения вам необходимо использовать или реализовать плагин, который захватывает выделенный текст, фильтрует его (возможно, через system()), а затем заменяет выделение результатом.

В моем подключаемом модуле SubstituteExpression есть сопоставление {Visual}g=, которое может фильтровать с помощью выражений Vimscript, функций и команд Vim, а также внешних команд.

express.vim Тома Макдональда предлагает практически идентичную реализацию. Он также позволяет "на лету" создавать операторы через :MapExpress и :MapSubpress, для чего я бы использовал свой TextTransform plugin, который вам в любом случае необходимо установить как зависимость. Мой плагин предлагает более продвинутые (кросс-режимные) повторы и :Ex - вариант выражения команды, но имеет две большие зависимости, которые вам также необходимо установить.

1
Ingo Karkat 24 Сен 2018 в 08:57