Рефакторинг в Vim

100

Конечно, возможность рефакторинга в IDE бесценна для многих, я почти никогда не делаю этого, когда пишу код, но я могу попытаться сделать это при редактировании чужого источника. Как выполнить такую ​​тривиальную задачу с несколькими файлами в Vim?

Я нашел этот плагин для рефакторинга Ruby, но как насчет «любого» языка?

Гельмут Гранда
источник
2
Рефакторинг сильно зависит от языка. Вам нужно искать определенные надстройки для каждого интересующего вас языка. Вы, вероятно, найдете надстройки для одних и не для других. Если есть что-то, что вы хотите и не можете найти, то, если вы амбициозны, вы можете попробовать написать его, используя существующее дополнение для другого похожего языка в качестве отправной точки.
Стив Йоргенсен
2
VIM предназначен для редактирования отдельных файлов и, возможно, файлов в каталоге, а не проектов . Многие рефакторинги, поддерживаемые IDE, повлияют на файлы во всем проекте (например, переименование класса). Я думаю, что было бы сложно сделать это «правильно» с помощью такого редактора, как (g) VI (m), до такой степени, что я думаю, что компании или крупному проекту придется взяться за это. В основном им пришлось бы анализировать каждый язык, чтобы избежать простых подстановок строк и стать склонными к ошибкам (ctags дает некоторые из них), а также соответствующие типы проектов (чтобы знать, какие файлы редактировать).
Мерлин Морган-Грэм
1
Спасибо за комментарии, я думаю, что здесь все начинает усложняться, и попытка согнуть VIM в IDE не является элегантным решением для использования только одной программы для редактирования нескольких языков. Я действительно не хочу отказываться от VIM из-за того, что некоторые из «продвинутых» функций доступны в IDE.
Helmut Granda
@ MerlynMorgan-Graham - Некоторые люди просто хранят свой код в нескольких (возможно, больших) файлах. Полностью устраняет эту проблему.
Rook
7
@ldigas: Это поможет обойти проблему. Но это совершенно противоречит рекомендуемой практике для некоторых языков (например, Java). В основном код меняется под нужды инструмента, хотя на самом деле должно быть наоборот.
Мерлин Морган-Грэм,

Ответы:

79

Я согласен с парадигмой «Vim - это не IDE». Но бывают случаи, когда IDE нет. Вот что я использую в таких ситуациях:

: grep,: vimgrep,: Ag,: Ggrep

Рефакторинг, который больше связан с регулярными заменами, я обычно использую : grep в моем дереве проекта, а затем записываю макрос для выполнения рефакторинга -: g и: s - это не проблема. Обычно это позволяет мне быстро изменять большое количество файлов с минимальными усилиями. Честно говоря, я использую этот метод больше, чем любой другой.

В зависимости от вашего рабочего процесса встроенные команды могут быть медленными / неудобными. Если вы используете git, вы захотите использовать отличный плагин Fugitive и его :Ggrepкоманду для поиска только файлов, проверенных в git. Еще мне нравится Silver Searcher за его скорость.

: argdo,: cdo и: bufdo

: cdo и : argdo удобны для выполнения команд vim над набором файлов.

командная строка

Когда становится труднее определить список файлов, требующих изменений, :vimgrepя прибегаю к командам командной строки grep / find для более тщательного анализа списка файлов, которые мне нужно реорганизовать. Сохраните список в текстовый файл и используйте :eмэшап записей макросов, чтобы внести необходимые изменения.

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


Обновить

С момента написания этой статьи на vimcasts.org было опубликовано больше видеопередач с описанными мною методами (я призываю вас посмотреть ВСЕ Vimcast! ). Для рефакторинга посмотрите эти:

Вимгольф - также отличный способ практиковаться.

Повсеместное распространение серверов протокола языкового сервера с тех пор, как я написал этот ответ, также принесло некоторую возможность рефакторинга в Vim (и другие редакторы). ИМО, они далеки от того, чтобы уравнять возможности рефакторинга, которые вы могли бы увидеть в специально созданной среде IDE (я использую их и предпочитаю coc и ALE). Смотрите другие ответы на этот вопрос для получения дополнительной информации!

dsummersl
источник
12
Рефакторинг - это НАМНОГО больше, чем сопоставление с образцом, поэтому для его безопасной автоматизации необходимы IDE. Очевидно, что вы можете сделать это вручную, но, учитывая доступные варианты и то, что в большинстве случаев безопаснее делать это вручную, зачем вам вообще рассматривать любой другой вариант?
Катберто Окампо
1
@CutbertoOcampo Я согласен с вами до некоторой степени: в зависимости от множества аспектов проекта (структуры, языка (языков), навыков и ресурсов персонала, и многих других), МОЖЕТ быть отличный инструмент рефакторинга, применимый к вашей проблеме. Мой ответ применим к ситуациям, когда это неправда, и вы хотите решить проблему в Vim.
dsummersl
2
это нормально, я понимаю, что люди могут чувствовать себя более комфортно, используя свои давние любимые инструменты, и что есть некоторые хаки, которые могут работать действительно хорошо, возможно, лучше, чем любая другая среда разработки, но для нестандартных -box Я бы сказал, что настоящая IDE будет работать лучше для большинства пользователей. Я бы подумал о ситуации на 80-20% (даже больше, с балансом в пользу IDE).
Катберто Окампо,
1
Идеи есть практически для каждого языка. Попытка провести рефакторинг с помощью vim или regex звучит совершенно безумно. Зачем тебе вообще пытаться?
роллы
1
@rolls должен быть достаточно мощным, чтобы захватить нужную машину случайного коллеги с помощью not-your-ide или любого другого cfg, с которым вы можете жить, и оставить хорошее впечатление (не для «просто впечатления», а для репутации и будущего положения).
кровавый
29

Протокол языкового сервера (LSP)

Протокол языкового сервера содержит функцию интеллектуального переименования символов в проекте:

https://microsoft.github.io//language-server-protocol/specifications/specification-3-14/#textDocument_rename

Например, следующий языковой сервер поддерживает это:

Вы можете найти другие языковые серверы по адресу https://langserver.org/ .

Vim

Клиент-редактор vim необходим для использования их в vim. Существуют следующие варианты:

  1. LanguageClient-neovim (требуется ржавчина) предлагает отображение:

     nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (требуется node.js) предлагает сопоставление:

     " Remap for rename current word
     nmap <leader>rn <Plug>(coc-rename)
    
  3. Ale имеет

     nnoremap <silent> <Plug>(ale_rename) :ALERename<Return>
    

    Ale не определяет никаких сочетаний клавиш. Это должен делать пользователь.

  4. vim-lsp предоставляет следующую команду

     :LspRename
    

Как и в случае с Ale, отображение не предлагается. Однако, конечно, вы можете определить его следующим образом

    nmap <leader>r <plug>(lsp-rename)

( <leader>rдолжен быть заменен на ваш выбор; я не знаю, с чем согласны большинство плагинов)

  1. vim-lsc имеет сопоставление по умолчанию:

     'Rename': 'gR'
    

См. Также YouCompleteMe, который также поддерживает LSP.

Неовим

Neovim имеет начальную встроенную поддержку lsp с 13.11.2019

См. Общие конфигурации LSP на https://github.com/neovim/nvim-lsp

Однако я не мог понять, как работает умное переименование. Если кто-то знает это, обновите этот раздел.

Другие рефакторинги

Я не знаю, есть ли в планах протокол LSP для поддержки более сложных рефакторингов, таких как изменение структуры класса, добавление параметров к методам / функциям или перемещение метода в другой класс. Список рефакторингов см. На https://refactoring.com/catalog/ .

Hotschke
источник
К сожалению, поддержка рефакторинга в LSP в настоящее время довольно слабая по сравнению с существующим уровнем техники. github.com/Microsoft/language-server-protocol/issues/61
Микаэль,
2
AFAIK, что переименование для coc-renameработает только с текущим буфером. Он не обновлял использование экспортированного имени глобально в проекте (в файлах).
oligofren
16

Python

Для языка Python следующие плагины предоставляют «умные» возможности переименования для vim:

Hotschke
источник
13

C-Семья

  1. Попробуйте плагин Clighter для переименования-рефакторинга для семейства c. Он основан на clang, но есть ограничения, и плагин помечен как устаревший.

    Предлагаемое сопоставление Clighter :

     nmap <silent> <Leader>r :call clighter#Rename()<CR>
    

    Обратите внимание, что преемник плагина clighter8 удалил функцию переименования в коммите 24927db42 .

  2. Если вы используете neovim, вы можете взглянуть на зажим плагина . Это предполагает

     nmap <silent> <Leader>r :call ClampRename()<CR>
    
BB Chung
источник
5

Я написал этот плагин для общего рефакторинга. Он по-прежнему требует многих улучшений. Когда-нибудь в будущем я постараюсь отказаться от ctags в пользу clang для рефакторинга C и C ++.

Люк Эрмитт
источник
5

Плагин YouCompleteMe (YCM) (20к звезд на github)

http://ycm-core.github.io/YouCompleteMe/#the-refactorrename-new-name-subcommand

:h RefactorRename-new-name

В поддерживаемых типах файлов эта команда пытается выполнить семантическое переименование идентификатора под курсором. Это включает переименование деклараций, определений и использований идентификатора или любые другие соответствующие языку действия. Конкретное поведение определяется используемым семантическим механизмом.

Подобно FixItэтой команде, эта команда применяет автоматические изменения к вашим исходным файлам. Операции переименования могут включать в себя изменения нескольких файлов, которые могут быть открыты или не открыты в буферах Vim в данный момент. YouCompleteMe сделает все это за вас. Поведение описано в следующем разделе.

Поддерживаются типы файлов: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs.

По умолчанию сопоставление отсутствует.

Hotschke
источник
Итак, пока это работает только для javascript, typescript и java?
SR
Чтобы эта работа работала с несколькими файлами в семействе C (используя clangd), вам необходимо добавить это в свой .vimrc: let g: ycm_clangd_args = ['-cross-file-rename']
jav
4

Возможно, не самое элегантное решение, но оно мне показалось очень удобным: я использую ECLIM для подключения VIM и Eclipse. Конечно, все мое редактирование исходного кода выполняется в VIM, но когда пришло время провести рефакторинг, можно воспользоваться превосходными возможностями Eclipse в этом вопросе.

Попробуйте.

fjrg76
источник
3

Плагин Factorus

Существует еще один плагин vim, предназначенный для рефакторинга, под названием factorus, который доступен на github .

В настоящее время (2017-12) он поддерживает языки

  • c,
  • java и
  • питон.
Hotschke
источник
2

Поместите курсор на имя для рефакторинга и введите

gd(или gDесли вы выполняете рефакторинг глобальной переменной).

затем

cgn новое имя esc

а также

. один или несколько раз для рефакторинга следующего вхождения (й)

или

:%norm . для одновременного рефакторинга всех вхождений в буфере.

Геремия
источник
1

Я пишу много кода C / C ++ в vim. Наиболее распространенный рефакторинг, который я выполняю, - это переименование переменных, имен классов и т. Д. Обычно я использую :bufdo :%s/source/dest/gпоиск / замену в файлах, что почти то же самое, что и переименование, предоставляемое большими IDE.
Однако в моем случае я обнаружил, что обычно переименовываю похожие сущности, написанные в разных регистрах (например, CamelCase, snake_case и т. Д.), Поэтому я решил написать небольшую утилиту, чтобы помочь с таким поиском «умных» случаев / заменить, он размещен здесь . Это утилита командной строки, а не плагин для vim, надеюсь, вы найдете ее полезной.

Дкрикун
источник
0

Для рефакторинга, если вы используете Unite (а вы должны это делать ), вы можете затем использовать vim-qfreplace и упростить его. Посмотрите это видео, которое демонстрирует, как это работает. Как только ваш рабочий процесс настроен, вы можете сделать некоторые сопоставления для его оптимизации (вместо того, чтобы вводить большинство вещей, как в видео).

BenC
источник
0

Комбинация двух плагинов: vim-ripgrep , чтобы находить файлы и помещать результаты в окно quickfix, и quickfix-отражатель, чтобы сохранять изменения прямо в окне quickfix и автоматически сохранять каждое изменение в файлах.

Джейсон
источник
0

Я бы подумал об использовании версии emacs для spacemacs. Он использует те же режимы и большинство нажатий клавиш, что и Vim, но имеет гораздо больше надстроек из-за его шепелявого характера. Если вы хотите программировать на C ++, вы просто добавляете слой C ++, и большая часть IDE уже настроена для вас. Для других интерпретируемых языков, таких как python или bash, вам не нужно оставлять spacemacs, чтобы использовать их. У них даже есть способ запускать блоки кода прямо в вашем тексте, что отлично подходит для грамотного программирования или воспроизводимого программирования, когда код и данные находятся в одном файле. Оба сделаны как текст.

Spacemacs гораздо тяжелее справляется с начальной загрузкой, но дополнительные вещи, которые вы можете с ним сделать, стоят нескольких секунд затрат на запуск. Однослойный орг-режим стоит попробовать. Это лучший планировщик, программист, дневник / список дел, который я когда-либо использовал.

К. Келли Осборн
источник
0

Идти

  1. Инструмент godoctor ( github ) поддерживает несколько возможностей рефакторинга.
  • Переименовать
  • Функция извлечения
  • Извлечь локальную переменную
  • Переключить var ⇔: =
  • Добавить заглушки Godoc

Существует плагин vim https://github.com/godoctor/godoctor.vim, который делает их доступными

С курсором в том, что нужно переименовать:

:Rename <newname>

Выделение блока для извлечения:

:Refactor extract newfunc
  1. энергично

    • Точное типизированное переименование идентификаторов с помощью :GoRename.
  2. Языковой сервер gopls

Hotschke
источник