Vim - могу ли я передать несколько аргументов в пользовательскую команду без написания функции
Я написал следующую пользовательскую команду в моем файле.vimrc:
command! -nargs=+ Sub :%s/<args>/g
Это позволяет мне заменить одно слово на другое и выполняется так:
:Sub <word>/<new word>
Я бы предпочел писать команды с несколькими аргументами, например так:
:Sub <word> <new word>
Могу ли я переписать команду, чтобы принять несколько аргументов?
В идеале я хотел бы что-то вроде этого:
command! -nargs=+ Sub :%s/<arg1>/<arg2>/g
Заранее спасибо.
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
команда, и поместите курсор прямо посередине.