Зміна імен змінних у Vim


96

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

Було б непогано мати якусь команду, яка могла б допомогти мені змінити назву змінної на щось більш значуще, поки я в процесі читання коду, щоб я міг прочитати решту швидше.

Чи є якась команда у Vim, яка могла б дозволити мені швидко це зробити?

Я не думаю, що регулярні вирази будуть працювати, оскільки:

  1. одне і те саме ім'я однієї літери може мати різне призначення в різних блоках масштабування

  2. така ж комбінація літер може бути частиною іншого більшого імені var, або в рядку чи коментарі ... не хотіла б їх змінювати

Будь-які відомі рішення?

Відповіді:


198

Далі описано, як перейменувати змінну, яка визначена у поточній області {}.

Наведіть курсор на змінне використання. Натисніть 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.


40
+1 за вивчення більше 5 нових трюків Vim, які я мав би знати раніше. Дякую
Кенні Мейєр

6
Примітка: gd не працює, щоб знайти змінну в безпосередній області визначення у режимі Javascript у macvim. Це призводить мене до першого використання імені змінної в якійсь функції у файлі :( Якщо ви знаходитесь у певній області і хочете вибрати цю область, "va {" - "візуальний вибір навколо {" - це шлях Думаю.
Шрікумар

3
Трохи вдосконалена версія: gist.github.com/048616a2e3f5d1b5a9ad пропонує користувачеві, показує старе ім'я, відновлює позицію курсору після заміни
Енді Рей

7
+1 дуже хороший віземінер (думаю, що я щойно ввів новий термін). Примітка: Насправді мені потрібно було :двічі натиснути двокрапку ( ). Перший раз, коли я натиснув, я побачив :'<,'>. Якби я просто набрав s/звідти, це не спрацювало; Мені довелося набрати ще одну товсту кишку до s/.
Келвін,

6
Зверніть увагу, що вам не потрібна <C-R>команда заміни, просто пропустивши пошук, vim використовуватиме останній шаблон пошуку, який у цьому випадку був створений з gdкоманди. Тож просто робити :s//<newname>/gcбуде достатньо.
shangxiao

10

AFAIK, фактична підтримка рефакторингу у VIM відсутня. Роблячи перейменування з наміром рефактора, я зазвичай дотримуюсь таких запобіжних заходів:

  1. Обмежте обсяг змін моїми знаками використання.
  2. Вводячи регулярний вираз, поставте ім'я в дужки \ <і>. Це змусить його відповідати цілому слову, що зменшує типи неправильних перейменувань, які відбуватимуться.
  3. Не робіть багаторядкову заміну, щоб зменшити ймовірність поганої заміни
  4. Уважно перегляньте різницю коду, якщо це щось інше, ніж незначна зміна.

Моя кінцева зміна виглядає приблизно так

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

Я хотів би помилитися, оскільки для VIM не існує інструменту рефакторингу, але я цього не бачив.


У Perl ви також можете додати тип до шаблону пошуку. тобто $ для скалярів, @ для масивів,% для хешів
Nathan Fellman

@Nathan: на жаль, у Perl (5.X) це трохи складніше, оскільки sigil масивів і хешів змінюється із використанням:% hash -> весь хеш, $ hash {ключ} -> одне значення, @hash { qw / ab /} хеш-фрагмент.
user55400 02.03.09

10

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

Я здивований, ніхто не запропонував цього:

* :s// НОВА ІМЯ /gc

Це *те саме, що gn- він шукає наступне повторення слова під курсором І стає останнім пошуковим шаблоном, тому, коли ви опускаєте шаблон пошуку в команді-заміннику, VIM припускає, що це шаблон для пошуку.

Для невеликої кількості копій var, ще швидшої:

* cw <esc>Потім NEWNAME повторіть n.для інших випадків

Шукати входження cw- це команда для слова зміни , nпереходить до наступного входження останнього шуканого терміна і .повторює останню команду (а це слово змінити на НОВЕ ІМЯ )

(Кредити за те, що я все це знаю, переходять до @doomedbunnies на Reddit )

Ще один цікавий фокус: ( кредити @ nobe4 )

* cgn <esc>Потім NEWNAME повторіть .для інших випадків

cgnє "змінити будь-який результат (знайти наступне входження)". Тепер, коли це остання команда , вам не потрібно nпереходити до наступного входження, тому знову буде менше обведень і, що більш важливо, не потрібно чергувати nі .. Але, очевидно, цей недолік має відсутність способу пропустити подію.

Ось деякі переваги:

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

8

Помістіть це у свій .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так, щоб бути повторно вставлений в шаблоні заміни.


3

Ви можете використовувати модифікатор 'c' у глобальному пошуку та заміні, який вимагатиме підтвердження для кожної заміни. Це зайняло б більше часу, але це може працювати для файлу коду, що не є простою:

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

С означає підтвердження.


I позначає ігнорувати регістр. Ви хочете c, підтверджуйте кожну зміну.
Michael Kristofik

ой .. вибачте за це .. Виправлена ​​відповідь
Аднан

Відповідь все ще не виправлено повністю;)
user55400 02.03.09

ви мали на увазі втекли долар? Це щось на зразок моїх особистих уподобань. $ працює без втечі, а також із і оскільки у світі регулярних виразів і в vi $ має особливе значення, мені подобається уникати його просто для ясності.
Аднан

0

У c ви можете досягти певного прогресу за допомогою cscope. Він робить спробу зрозуміти синтаксис, тому мав би шанс дізнатися, коли буква є змінною.


0

Якщо це стосується декількох файлів, ви можете поглянути на sed. Використовуйте find, щоб захопити файли та xargs плюс sed для заміни. Скажімо, ви хочете замінити на a_better_name у всіх файлах, що відповідають * .c, ви могли б це зробити

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

Майте на увазі, що це замінить ВСІ випадки a, тому вам може знадобитися більш надійний регулярний вираз.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.