1

Я написал следующую команду в моем файле .vimrc:

command! -nargs=+ Sub :%s/<args>/g

Это позволяет мне заменить одно слово на другое и выполняется так:

:Sub <word>/<new word>

Я бы предпочел писать команды с несколькими аргументами, например так:

:Sub <word> <new word>

Могу ли я переписать команду, чтобы принять несколько аргументов?

В идеале я хотел бы что-то вроде этого:

command! -nargs=+ Sub :%s/<arg1>/<arg2>/g

Заранее спасибо.

1 ответ1

1

Сделайте разбор самостоятельно

Если вы используете :help <q-args>, вы получите строку в кавычках, которую вы можете split() на две разделенные пробелами части:

command! -nargs=+ Sub execute '%substitute/' . split(<q-args>, ' ')[0] . '/' . split(<q-args>, ' ')[1] . '/g'

Мы можем избежать синтаксического анализа дважды с помощью небольшого количества метапрограммирования (call()) и printf():

command! -nargs=+ Sub execute call('printf', ['%%substitute/%s/%s/g'] + split(<q-args>, ' '))

Это работает, но обработка ошибок все еще не хороша (если вы передадите только один аргумент, он будет жаловаться на E766: Insufficient arguments for printf()). Вы получите больше контроля, извлекая код в функцию :function

Vim может разобрать аргументы

Отдельная :function также позволяет Vim выполнять анализ аргументов за вас с помощью :help <f-args>.

command! -nargs=+ Sub call Sub(<f-args>)
function! Sub( ... )
    execute printf('%%substitute/%s/%s/g', a:1, a:2)
endfunction

С помощью функции вы можете легко проверить правильность количества аргументов:

function! Sub( ... )
    if a:0 != 2
        echo "Need two arguments"
        return
    endif
    ...

Недостатком функции является то, что ошибки (например, шаблон не совпадает, буфер не модифицируется) приводят к многострочному недружественному сообщению об ошибке. try...catch нужно будет использовать для получения красивого однострочного сообщения об ошибке.

Бонус: где его взять оттуда

  • Поскольку вы скрываете команду :s (и используемые разделители) от пользователя, я думаю, что не обязательно требовать экранирования разделителей. Используйте escape(a:1, '/') вместо a:1 / a:2 .
  • С :help :command-range вы по-прежнему можете использовать команду по умолчанию для работы со всем буфером, но также разрешать пропуск других диапазонов.

Также подумайте, действительно ли команда набирает вес. Независимо от используемого синтаксического анализа, пробелы в аргументах проблематичны, недостаток, которого нет у оригинала :s . Единственное преимущество, которое я вижу, заключается в том, что набрать текст немного проще, но того же можно добиться с помощью сопоставления (ей), которое предварительно заполняет командную строку командой не завершено :s и помещает курсор прямо посередине.

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