Как быстро изменить имена переменных в Vim?

Я использую Vim для чтения большого количества кода C и Perl, содержащего много однобуквенных имен переменных.

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

Есть ли в Vim какая-нибудь команда, которая позволила бы мне сделать это быстро?

Я не думаю, что регулярные выражения будут работать, потому что:

  1. одно и то же однобуквенное имя может иметь разные цели в разных блоках области видимости; а также

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

Есть какие-нибудь известные решения?

Ответов (7)

Решение

Ниже показано, как переименовать переменную, которая определена в текущей области {} .

Переместите курсор к использованию переменной. Нажмите gd . Что означает - переместите курсор к определению. Теперь нажмите [{ - это приведет вас к началу обзора. Нажмите V - включит выбор Visual Line. Нажатие % - перейдет к противоположному, } таким образом выберет весь прицел. Нажать :s/ - начало подстановочной команды. <C-R>/ - вставит шаблон, соответствующий имени переменной (то имя, которое вы использовали до нажатия gd ). /newname/gc<CR> - будет инициировать поиск и заменять с подтверждением при каждом совпадении.

Теперь вам нужно записать макрос или, что еще лучше, сопоставить ключ.

Вот окончательные сопоставления:

" For local replace
nnoremap gr gd[{V%::s/<C-R>///gc<left><left><left>

" For global replace
nnoremap gR gD:%s/<C-R>///gc<left><left><left>

Поместите это в свой .vimrc или просто выполните. После этого нажатие gr на локальную переменную приведет вас к :s команде, где вы просто должны ввести new_variable_name и нажать Enter.

Если это связано с несколькими файлами, вы можете подумать о том, чтобы взглянуть на sed. Используйте find, чтобы получить ваши файлы, и xargs плюс sed для замены. Скажем, вы хотите заменить a на a_better_name во всех файлах, соответствующих * .c, вы можете сделать

найти . -name "* .c" | xargs sed -i -e 's / a / a_better_name / g'

Имейте в виду, что это заменит ВСЕ вхождения a, поэтому вам может потребоваться более надежное регулярное выражение.

Поместите это в свой .vimrc

" Function to rename the variable under the cursor
function! Rnvar()
  let word_to_replace = expand("<cword>")
  let replacement = input("new name: ")
  execute '%s/\(\W\)' . word_to_replace . '\(\W\)/\1' . replacement . '\2/gc'
endfunction

Назовите это с :call Rnvar()

expand("<cword>") получает слово под курсором. Строка поиска использует % для файла-сферы, а также \(\W\) шаблоны поиска символов без слов на границе слова , чтобы заменить, и сохранять их в переменных \1 и \2 так, чтобы быть повторно вставлен в шаблоне замены.

Я знаю, что это старый вопрос, и способ @mykola-golubyev, очевидно, является лучшим ответом для конкретного случая в вопросе OP (который, я полагаю, проходит через запутанный код, где у вас, вероятно, будет несколько блоков с одинаковыми именами var) ; но с таким названием вопроса многие люди, приходящие сюда из поисков Google, вероятно, ищут менее зависящие от ситуации способы переименования переменных в VIM - и они могут быть более краткими

Я удивлен, что никто не предложил такой способ:

* :s// НОВОЕ ИМЯ /gc

То * же самое, что и gn - он ищет следующее вхождение слова под курсором и становится последним искомым шаблоном, поэтому, когда вы опускаете шаблон поиска в команде замены, VIM предполагает, что это шаблон для поиска.

Для небольшого количества копий var еще быстрее:

* cw NEWNAME, <esc> затем повторите n.для других случаев

Поиск вхождения, cw это команда для изменения слова , n переходит к следующему вхождению последнего искомого термина и . повторяет последнюю команду (которая представляет собой изменение слова на NEWNAME )

(Благодарности за то, что я знаю все это, идут на @doomedbunnies на Reddit )

Еще один интересный трюк: ( кредиты на @ nobe4 )

* cgn NEWNAME, <esc> затем повторите .для других случаев

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

Вот некоторые преимущества:

  • нет сопоставления, нет .vimrc (или init.vim), поэтому вы можете использовать его в любой копии VIM, с которой столкнетесь (например, быстрая задача на каком-то VPS или машине вашего друга, где настройка VIM по-своему нарушит цель `` быстрого '' )
  • использование *или gnдля выбора слова выполняется очень быстро - всего одно нажатие клавиши (ну, скажем, 1,5)
  • используя *или gnследит за тем, чтобы в других словах не было совпадений, точно так же, как :%s/<C-R>//gcи. Лучше печатать :%s/\<OLDNAME\>/NEWNAME/gcвручную: я лично часто забываю использовать \<вещи, чтобы ограничивать совпадения только целыми словами.
  • Неиспользование области видимости приведет только к нескольким дополнительным штрихам, nчтобы пропустить нежелательные совпадения - возможно, даже меньше, чем дополнительные штрихи, необходимые для ограничения области действия. В обычных условиях ваши переменные, скорее всего, так или иначе локализованы в определенном блоке кода.

В c вы можете добиться некоторого прогресса с помощью cscope. Он пытается понять синтаксис, поэтому у него будет шанс узнать, когда буква была переменной.

Вы можете использовать модификатор 'c' в глобальном поиске и замене, который будет запрашивать подтверждение для каждой замены. Это займет больше времени, но может сработать для небольшого файла кода:

%s/\$var/\$foo/gc

C означает подтверждение.

AFAIK, в VIM нет реальной поддержки рефакторинга. При переименовании с целью рефакторинга я обычно принимаю следующие меры:

  1. Ограничьте объем изменения моими знаками использования.
  2. При вводе регулярного выражения заключите имя в скобки с \ <и>. Это приведет к совпадению всего слова, что уменьшит количество возможных неправильных переименований.
  3. Не выполняйте многострочную замену, чтобы снизить вероятность плохой замены
  4. Внимательно просмотрите код diff, если это что-то, кроме небольшого изменения.

Мое окончательное изменение выглядит примерно так

:'a,'bs/\<foo\>/bar

Я хотел бы ошибиться в том, что для VIM не существует инструмента рефакторинга, но я его не видел.