Как создать псевдоним для команды в Vim?

При программировании я предпочитаю текстовый редактор Vim, и поэтому я всегда сталкиваюсь с особенно неприятной проблемой.

Часто, когда мне нужно быстро сохранить буфер и перейти к другой разной задаче, я делаю типичный

:w

Тем не менее, мне всегда - что, кажется, более чем в 50% случаев - удается извлечь выгоду из этого :w. Естественно, Vim кричит на меня, потому что W - недопустимая команда:

E492: Not an editor command: W

У меня вопрос, как можно псевдоним двоеточие-команды в Vim. В частности, не могли бы вы проиллюстрировать, как использовать псевдоним W для w.

Мне известен процесс сопоставления ключей с определенными командами, но это не то, что я ищу.


person Sean    schedule 07.10.2010    source источник
comment
возможный дубликат Могу ли я (повторно) сопоставить команды в vim?   -  person Chris Morgan    schedule 23.05.2012
comment
Чтобы избежать :W, вы можете сопоставить ключ для выполнения сохранения. Если вы привыкли к какой-то программе, которая сохраняет с помощью Ctrl-s, есть следующие сопоставления из $ VIM / mswin.vim: " Use CTRL-S for saving, also in Insert mode noremap <C-S> :update<CR> vnoremap <C-S> <C-C>:update<CR> inoremap <C-S> <C-O>:update<CR>   -  person mMontu    schedule 23.05.2012
comment
Аналогичный вопрос об обмене Vi Stack: vi.stackexchange.com/q/2665/7244   -  person Flimm    schedule 24.08.2018


Ответы (7)


Чтобы оставить завершение нетронутым, попробуйте использовать

cnoreabbrev W w

Он заменит W в командной строке на w, но только если за ним не следует и не предшествует символ слова, поэтому :W<CR> будет заменен на :w<CR>, а :Write - нет. (Обратите внимание, что это влияет на любые совпадающие команды, включая те, которых вы не ожидали. Например, команда :saveas W Z будет заменена на :saveas w Z, поэтому будьте осторожны с этим.)

Обновлять

Вот как я бы это написал сейчас:

cnoreabbrev <expr> W ((getcmdtype() is# ':' && getcmdline() is# 'W')?('w'):('W'))

Как функция:

fun! SetupCommandAlias(from, to)
  exec 'cnoreabbrev <expr> '.a:from
        \ .' ((getcmdtype() is# ":" && getcmdline() is# "'.a:from.'")'
        \ .'? ("'.a:to.'") : ("'.a:from.'"))'
endfun
call SetupCommandAlias("W","w")

Это проверяет, что тип команды - :, а команда - W, так что это безопаснее, чем просто cnoreabbrev W w.

person ZyX    schedule 07.10.2010
comment
Для меня это самый безопасный и надежный ответ. - person Sean; 13.10.2010
comment
Если вы используете рекомендованное решение, имейте в виду, что обе из двух приведенных ниже команд будут работать как нижняя, что может дать неожиданный результат в зависимости от фактического содержимого буфера и настроек VIM: :%s/W/foo/g<CR> :%s/w/foo/g<CR> - person cprn; 25.04.2012
comment
Фактически, это будет означать, что W будет заменен где угодно на панели команд, в том числе, например, при поиске, поэтому s / W foo / bar / g будет преобразовано в s / w foo / bar / г. это может очень быстро раздражать. см. мой ответ для комплексного решения. - person airstrike; 22.05.2012
comment
Абсолютно; это ужасная идея. Вы не должны никогда, никогда, когда-либо делать это. - person Chris Morgan; 23.05.2012
comment
@kev Странная манера говорить «у вас тут проблемы». И сокращение с другой проблемой: type :W<C-v> W<Space> Но спасибо, это было исправлено. // У меня было две ошибки: getcmdline() is# 'w', что невозможно, и в результате поменяли местами 'w' и 'W'. - person ZyX; 27.07.2012
comment
@kev Кстати, использование регулярных выражений там, где они не нужны, плохо сказывается на производительности. Это не Perl, getcmdline()[0] is# 'W' служит той же цели. - person ZyX; 27.07.2012
comment
@CelsoDantas Тогда замените cnoreabbrev на cnoremap. С условием getcmdtype() … это не должно быть слишком навязчивым. Или определите два сокращения. - person ZyX; 26.04.2013
comment
@CelsoDantas Изменение файла с помощью какой-либо специальной команды с последующим немедленным завершением работы в любом случае опасно .... - person Kyle Strand; 20.06.2013
comment
Вы можете использовать cmdalias, чтобы упростить это до :Alias W w, и он сделает Магия getcmdline для вас. - person idbrii; 13.12.2013
comment
Что касается вашего редактирования, я сожалею только о том, что fun! в конечном итоге подошел к концу. - person Seldom 'Where's Monica' Needy; 21.03.2015
comment
У меня есть команда без аргументов, и чтобы ее развернуть, мне нужно нажать space. Можно ли этого избежать? - person user14416; 06.06.2016
comment
@ user14416 Для проверки того, что он расширяется, а не для получения его расширения. <Enter> расширяет аббревиатуры так же хорошо, как и пробел, только вы не можете проверить или отреагировать, если расширение нежелательно. - person ZyX; 07.06.2016
comment
@ZyX Извините, я не совсем понял ваш ответ. Я использую :Alias q qall. И :q<Enter> только q, но не :qall<Enter>, я что-то упускаю? - person user14416; 07.06.2016
comment
@ user14416 Что такое «: Псевдоним»? Если я использую cnoreabbrev <expr> q ((getcmdtype() is# ':' && getcmdline() is# 'q')?('echo 1'):('echo 2')), я получаю 1 при вводе :q<Enter>, как и ожидалось. Если я использую call SetupCommandAlias('q', 'echo 1') (с функцией из моего ответа), я получаю 1, как и ожидалось. Если вы получили ошибочную команду где-то не из этого ответа, почему вы спрашиваете здесь? - person ZyX; 07.06.2016
comment
@ZyX Причина в том, что у меня было отображение cmap <Cr> <Cr>. Почему это не должно работать, когда у меня есть такое отображение? - person user14416; 10.06.2016
comment
@ user14416 cmap <CR> <CR> не вмешивается в работу с такими псевдонимами. Что такое cnoremap. Проверьте в чем разница в справке. - person ZyX; 10.06.2016

При дополнительном поиске я обнаружил, что кто-то задал почти такой же вопрос как я.

:command <AliasName> <string of command to be aliased>

сделает свое дело.

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

person Sean    schedule 07.10.2010
comment
Использование команды: - хорошее решение. : cnoreabbrev не понимает cmd1 | cmd2, команда: понимает. - person Pavel Strakhov; 14.04.2011
comment
Менее запутанный способ написать это: :command AliasName string of command to be aliased - person Alec Jacobson; 21.08.2013
comment
Это не будет обрабатывать / пересылать какие-либо command аргументы, такие как -nargs, -complete и т. Д. - person blueyed; 11.02.2014
comment
А как насчет :Q! или :W!? - person Jack; 31.07.2014
comment
Чтобы быть очень буквальным: поместите :command W w в .vimrc файл. - person isomorphismes; 25.09.2014

Я считаю, что сопоставление клавиши ; с : было бы лучшим решением и сделало бы вас более продуктивным при вводе других команд.

nnoremap ; :
vnoremap ; :
person fent    schedule 13.02.2014
comment
Это лучший совет для vim. Я так привык к этому сейчас, что каждый раз, когда я сталкиваюсь с нормальным поведением, мне нужно несколько попыток, чтобы переобучить свой разум. - person airstrike; 24.02.2015
comment
Это не ответ на вопрос. - person Flimm; 24.08.2018
comment
@Flimm Нет, но это решает проблему OP. - person Dessa Simpson; 24.09.2018
comment
При использовании t или f обычно можно использовать ; для перехода к следующему вхождению. Можно смело отобразить это другим способом, даже если вы сопоставили точку с запятой с двоеточием. Не будет цикла псевдонимов. nnoremap : ; - person Luc; 05.03.2019
comment
Это прекрасно, спасибо. - person ddg; 22.01.2021

Лучшее решение включает в себя написание пользовательской функции для обработки сокращений, которые появляются только в начале командной строки.

Для этого добавьте следующий файл vimrc или где-нибудь еще.

" cabs - less stupidity                                                      {{{
fu! Single_quote(str)
  return "'" . substitute(copy(a:str), "'", "''", 'g') . "'"
endfu
fu! Cabbrev(key, value)
  exe printf('cabbrev <expr> %s (getcmdtype() == ":" && getcmdpos() <= %d) ? %s : %s',
    \ a:key, 1+len(a:key), Single_quote(a:value), Single_quote(a:key))
endfu
"}}}

 

" use this custom function for cabbrevations. This makes sure that they only
" apply in the beginning of a command. Else we might end up with stuff like
"   :%s/\vfoo/\v/\vbar/
" if we happen to move backwards in the pattern.

" For example:
call Cabbrev('W', 'w')

Несколько полезных сокращений из исходного материала где я нашел это:

call Cabbrev('/',   '/\v')
call Cabbrev('?',   '?\v')

call Cabbrev('s/',  's/\v')
call Cabbrev('%s/', '%s/\v')

call Cabbrev('s#',  's#\v')
call Cabbrev('%s#', '%s#\v')

call Cabbrev('s@',  's@\v')
call Cabbrev('%s@', '%s@\v')

call Cabbrev('s!',  's!\v')
call Cabbrev('%s!', '%s!\v')

call Cabbrev('s%',  's%\v')
call Cabbrev('%s%', '%s%\v')

call Cabbrev("'<,'>s/", "'<,'>s/\v")
call Cabbrev("'<,'>s#", "'<,'>s#\v")
call Cabbrev("'<,'>s@", "'<,'>s@\v")
call Cabbrev("'<,'>s!", "'<,'>s!\v")
person airstrike    schedule 22.05.2012
comment
Есть встроенная функция string(), которая делает то же самое, что и ваша Single_quote(). - person ZyX; 23.05.2012

Предположим, вы хотите добавить псевдоним для команды tabnew в gvim. вы можете просто ввести следующую команду в свой .vimrc файл (если не в домашней папке, то создайте ее)

cabbrev t tabnew
person Sandip    schedule 27.02.2013
comment
Это приведет к замене такой команды, как :saveas t example, на :saveas tabnew example - person Flimm; 24.08.2018

Может быть, вы хотите сопоставить одну из своих функциональных клавиш (F1..F12) с: w? Затем поместите это в свой .vimrc:

noremap  <f1> :w<return>
inoremap <f1> <c-o>:w<return>

(ctrl-o в режиме вставки временно переключает в нормальный режим).

person Benoit    schedule 07.10.2010

Самым безопасным и простым является такой плагин, как cmdalias.vim или мое недавнее обновление vim-alias, который учитывает

  • предшествующие пробелы или модификаторы, такие как :sil(ent)(!) или :redi(r),
  • модификаторы диапазона, такие как '<,'> для текущего визуального выделения,
  • экранировать специальные символы, такие как кавычки и
  • проверьте, является ли выбранный псевдоним допустимым сокращением командной строки.
person Enno    schedule 11.04.2016