Refaktoryzacja w Vimie

99

Oczywiście fakt, że można refaktoryzować w IDE jest dla wielu bezcenny. Rzadko kiedy to robię, kiedy koduję, ale mogę próbować to zrobić podczas edycji czyjegoś źródła. Jak wykonujesz tak trywialne zadanie na wielu plikach w Vimie?

Znalazłem tę wtyczkę do refaktoryzacji Rubiego, ale co powiesz na „dowolny” język?

Helmut Granda
źródło
2
Refaktoryzacja jest bardzo specyficzna dla języka. Musisz szukać konkretnych dodatków dla każdego języka, który Cię interesuje. Prawdopodobnie znajdziesz dodatki dla niektórych, a nie dla innych. Jeśli jest taki, którego chcesz i nie możesz znaleźć, to jeśli czujesz się ambitny, możesz spróbować go napisać, korzystając z istniejącego dodatku dla innego podobnego języka jako punktu wyjścia.
Steve Jorgensen
2
VIM jest przeznaczony do edycji pojedynczych plików, a może plików w katalogu - nie projektów . Wiele refaktoryzacji obsługiwanych przez IDE będzie miało wpływ na pliki w całym projekcie (np. Zmiana nazwy klasy). Myślę, że byłoby to trudne, aby zrobić to „dobrze” z edytorem takim jak (g) VI (m), do punktu, w którym myślę, że firma lub duży projekt musiałby się tym zająć. Zasadniczo musieliby przeanalizować każdy język, aby uniknąć prostego zastępowania ciągów i stać się podatnym na błędy (ctags daje to trochę ), a także odpowiednie typy projektów (aby wiedzieć, które pliki edytować).
Merlyn Morgan-Graham
1
Dzięki za komentarze, myślę, że tutaj sprawy zaczynają się komplikować, a próba zgięcia VIM-a do IDE nie jest eleganckim rozwiązaniem do używania tylko jednego programu do edycji wielu języków. Naprawdę nie chcę rezygnować z VIM-a ze względu na niektóre „zaawansowane” funkcje dostępne w IDE.
Helmut Granda,
@ MerlynMorgan-Graham - Niektórzy ludzie po prostu przechowują swój kod w kilku (być może dużych) plikach. Całkowicie unika tego problemu.
Wieża
7
@ldigas: To rozwiązałoby problem. Ale jest to dość sprzeczne z zalecanymi praktykami dla niektórych języków (np. Java). Zasadniczo kod wygina się w celu dopasowania do potrzeb narzędzia, podczas gdy naprawdę powinno być na odwrót.
Merlyn Morgan-Graham

Odpowiedzi:

78

Zgadzam się z paradygmatem „Vim nie jest IDE”. Ale są chwile, kiedy nie ma IDE. Oto, czego używam w takich sytuacjach:

: grep,: vimgrep,: Ag,: Ggrep

Refaktoryzacja, która ma więcej wspólnego z regularnymi zamianami, zwykle używam : grep w moim drzewie projektu, a następnie nagrywam makro, aby wykonać refaktor -: g i: s nie wymagają myślenia. Zwykle pozwala mi to szybko zmodyfikować dużą liczbę plików przy niewielkim wysiłku. Szczerze mówiąc, używam tej metody częściej niż innych.

W zależności od przepływu pracy wbudowane polecenia mogą być powolne / niewygodne. Jeśli używasz git, będziesz chciał użyć doskonałej wtyczki Fugitive i jej :Ggreppolecenia do wyszukiwania tylko plików sprawdzonych w git. Podoba mi się też Silver Searcher za jego szybkość.

: argdo,: cdo oraz: bufdo

: cdo i : argdo są przydatne do wykonywania poleceń vima na zestawie plików.

wiersz poleceń

Kiedy trudniej jest określić listę plików, które wymagają zmian, korzystam :vimgrepz polecenia grep / find w wierszu poleceń, aby dokładniej określić listę plików, które muszę refaktoryzować. Zapisz listę w pliku tekstowym i użyj :eoraz zestawu nagrań makr, aby wprowadzić zmiany, które muszę wprowadzić.

Uważam, że im mniej zardzewiałe zachowuję moje umiejętności nagrywania makr, tym bardziej przydatne są dla mnie Vim do refaktoryzacji: czuję się komfortowo zapisując / przywracając z rejestrów, zwiększając / zmniejszając zmienne liczników rejestrów, czyszcząc / zapisując nagrania makr do pliku do późniejszego wykorzystania itp.


Aktualizacja

Od czasu napisania tego artykułu więcej wideokastów dotyczących metod, które opisuję, zostało opublikowanych na vimcasts.org (zachęcam do obejrzenia WSZYSTKICH Vimcastów! ). W przypadku refaktoryzacji obejrzyj te:

Vimgolf to także świetny sposób na ćwiczenie.

Wszechobecność serwerów Language Server Protocol, odkąd napisałem tę odpowiedź, przyniosła również Vimowi (i innym edytorom) pewne możliwości refaktoryzacji. IMO są dalekie od zrównania możliwości refaktoryzacji, które można zobaczyć w specjalnie zbudowanym IDE (używam ich, a wolę coc i ALE). Zobacz inne odpowiedzi na to pytanie, aby uzyskać więcej informacji!

dsummersl
źródło
12
Refaktoryzacja to WIĘCEJ więcej niż dopasowywanie wzorców, dlatego IDE są potrzebne, aby zautomatyzować to w bezpieczny sposób. Oczywiście możesz to zrobić ręcznie, ale biorąc pod uwagę dostępne opcje i że w większości przypadków bezpieczniej jest to zrobić ręcznie, dlaczego miałbyś w ogóle rozważyć jakąkolwiek inną opcję?
Cutberto Ocampo
1
@CutbertoOcampo Do pewnego stopnia zgadzam się z Tobą: w zależności od niezliczonych aspektów projektu (struktura, język (i), umiejętności personelu i zasoby, by wymienić tylko kilka), MOŻE być świetne narzędzie do refaktoryzacji, które można zastosować do Twojego problemu. Moja odpowiedź dotyczy sytuacji, gdy to nieprawda i chcesz rozwiązać problem w Vimie.
dsummersl
2
w porządku, rozumiem, że ludzie mogą czuć się bardziej komfortowo, robiąc rzeczy przy użyciu preferowanych od dawna narzędzi, i że jest kilka hacków, które mogą działać naprawdę dobrze, prawdopodobnie lepiej niż jakiekolwiek inne środowisko IDE, ale poza -box Rozwiązanie Powiedziałbym, że rzeczywiste IDE działałoby lepiej dla większości użytkowników. Myślałbym o sytuacji w rodzaju 80-20% (nawet więcej, z równowagą na korzyść IDE).
Cutberto Ocampo
1
Praktycznie w każdym języku jest pomysł. Próba refaktoryzacji za pomocą vim lub regex brzmi absolutnie szalenie. Dlaczego miałbyś spróbować?
rolki
1
@rolls jest wystarczająco silny, aby złapać potrzebną maszynę przypadkowego kolegi z nie-twoim-ide lub cfg, z którym możesz tylko żyć, i pozostawić dobre wrażenie (nie dla „tylko wrażenia”, ale dla reputacji i przyszłej pozycji).
krwawy
27

Protokół serwera języka (LSP)

Protokół serwera językowego zawiera funkcję inteligentnej zmiany nazw symboli w całym projekcie:

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

Na przykład obsługuje to następujący serwer językowy:

Więcej serwerów językowych można znaleźć pod adresem https://langserver.org/ .

Krzepkość

Klient edytora vim jest niezbędny, aby używać ich w vimie. Istnieją następujące opcje:

  1. LanguageClient-neovim (wymaga rdzy) sugeruje mapowanie:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (wymaga node.js) sugeruje mapowanie:

    " Remap for rename current word
    nmap <leader>rn <Plug>(coc-rename)
    
  3. Ale ma

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

    Ale nie definiuje żadnych skrótów klawiszowych. Musi to zrobić użytkownik.

  4. vim-lsp udostępnia następujące polecenie

    :LspRename
    

    Podobnie jak w Ale, nie jest zalecane mapowanie. Jednak oczywiście możesz zdefiniować jeden z poniższych

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

    ( <leader>rdo wymiany według twojego wyboru; nie wiem, na którą zgadza się większość wtyczek)

  5. vim-lsc ma domyślne mapowanie:

    'Rename': 'gR'
    

Zobacz także YouCompleteMe które ułatwia również LSP.

Neovim

Od tego czasu Neovim ma wbudowane wsparcie dla lsp 13.11.2019

Zobacz, aby zapoznać się z typowymi konfiguracjami dostawców LSP https://github.com/neovim/nvim-lsp

Nie mogłem jednak dowiedzieć się, jak działa inteligentna zmiana nazwy. Jeśli ktoś o tym wie, zaktualizuj tę sekcję.

Inne refaktoryzacje

Nie wiem, czy istnieją plany, aby protokół LSP obsługiwał bardziej złożone refaktoryzacje, takie jak zmiana struktury klasy, dodanie parametrów do metod / funkcji czy przeniesienie metody do innej klasy. Lista refaktoryzacji znajduje się pod adresem https://refactoring.com/catalog/ .

Hotschke
źródło
Niestety, wsparcie dla refaktoryzacji w LSP jest obecnie dość słabe w porównaniu ze stanem techniki. github.com/Microsoft/language-server-protocol/issues/61
Mickael
2
AFAIK, że zmiana nazwy coc-renamedziała tylko na bieżącym buforze. Nie zaktualizował użycia wyeksportowanej nazwy globalnie w projekcie (między plikami).
oligofren
16

Pyton

Dla języka Python następujące wtyczki zapewniają `` inteligentne '' możliwości zmiany nazwy dla vim:

  • jedi-vim( github )<leader>r
  • ropevim( github )CTRL-c r r
  • python-mode( github ):h pymode-rope-refactoring
Hotschke
źródło
13

Rodzina C.

  1. Wypróbuj wtyczkę Clighter do zmiany nazwy-refaktoryzacji dla rodziny c. Jest oparty na clang, ale istnieją ograniczenia, a wtyczka jest oznaczona jako przestarzała.

    Sugerowane mapowanie Clighter to

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

    Uwaga, następca wtyczki clighter8 usunął funkcję zmiany nazwy w zatwierdzeniu 24927db42 .

  2. Jeśli używasz neovim, możesz rzucić okiem na zacisk wtyczki . Sugeruje

     nmap <silent> <Leader>r :call ClampRename()<CR>
    
BB Chung
źródło
5

Napisałem tę wtyczkę do generycznej refaktoryzacji. Nadal wymaga wielu ulepszeń. Kiedyś w przyszłości spróbuję porzucić ctagi na rzecz clang dla refaktoryzacji C i C ++.

Luc Hermitte
źródło
4

Może nie jest to najbardziej eleganckie rozwiązanie, ale okazało się to bardzo przydatne: używam ECLIM do połączenia VIM i Eclipse. Oczywiście cała moja edycja kodu źródłowego odbywa się w VIM, ale kiedy nadejdzie czas na refaktoryzację, można w tej kwestii skorzystać z doskonałych możliwości Eclipse.

Spróbuj.

fjrg76
źródło
4

Plugin YouCompleteMe (YCM) (20 tys. Gwiazdek na github)

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

:h RefactorRename-new-name

W obsługiwanych typach plików to polecenie próbuje wykonać semantyczną zmianę nazwy identyfikatora pod kursorem. Obejmuje to zmianę nazw deklaracji, definicji i zastosowań identyfikatora lub wszelkie inne działania odpowiednie dla języka. Specyficzne zachowanie jest definiowane przez używany silnik semantyczny.

Podobnie jak FixItto polecenie stosuje automatyczne modyfikacje do plików źródłowych. Operacje zmiany nazwy mogą obejmować zmiany w wielu plikach, które mogą, ale nie muszą być otwarte w buforach Vima. YouCompleteMe zajmuje się tym wszystkim za Ciebie. Zachowanie opisano w następnej sekcji.

Obsługiwane w typach plików: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs

Domyślnie nie ma mapowania.

Hotschke
źródło
Więc na razie działa to tylko dla javascript, maszynopisu i javy?
SR
3

Plugin Factorus

Jest jeszcze jedna wtyczka vim przeznaczona do refaktoryzacji o nazwie factorus, która jest dostępna na github .

Obecnie (2017-12) obsługuje języki

  • do,
  • java i
  • pyton.
Hotschke
źródło
2

Umieść kursor na nazwie, aby refaktoryzować i pisać

gd(lub gDjeśli refaktoryzujesz zmienną globalną).

Następnie

cgn nowe imie esc

i

. jeden lub więcej razy, aby refaktoryzować następne wystąpienie (a)

lub

:%norm . aby jednocześnie refaktoryzować wszystkie wystąpienia w buforze.

Geremia
źródło
1

Piszę dużo kodu C / C ++ w vimie. Najczęstszym refaktoryzacją, którą wykonuję, jest zmiana nazw zmiennych, nazw klas itp. Zwykle używam :bufdo :%s/source/dest/gdo wyszukiwania / zamiany w plikach, co jest prawie takie samo jak zmiana nazwy zapewniana przez duże IDE.
Jednak w moim przypadku zauważyłem, że zwykle zmieniam nazwy podobnych podmiotów, pisane w różnych przypadkach (np. CamelCase, snake_case itp.), Więc zdecydowałem się napisać małe narzędzie, które pomoże w tego rodzaju wyszukiwaniu „inteligentnych skrzynek” / wymienić, jest hostowany tutaj . Jest to narzędzie wiersza poleceń, a nie wtyczka do vima, mam nadzieję, że okaże się przydatne.

dkrikun
źródło
0

Do refaktoryzacji, jeśli używasz Unite (a powinieneś), możesz użyć vim-qfreplace i uczynić to niezwykle prostym. Obejrzyj ten film, który pokazuje, jak to działa. Po ustawieniu przepływu pracy możesz wykonać pewne mapowania, aby go zoptymalizować (zamiast wpisywać większość rzeczy, jak na wideo).

BenC
źródło
0

Połączenie dwóch wtyczek: vim-ripgrep , aby znaleźć między plikami i umieścić wyniki w oknie quickfix, oraz quickfix-reflector, aby zapisać zmiany bezpośrednio w oknie quickfix i automatycznie zapisywać każdą zmianę w plikach.

Jason
źródło
0

Rozważałbym użycie emacsa w wersji spacemacs. Używa tych samych trybów i większości naciśnięć klawiszy co Vim, ale ma o wiele więcej dodatków ze względu na swoją naturę seplenienia. Jeśli chcesz programować w C ++, po prostu dodaj warstwę c ++ i większość IDE jest już skonfigurowana dla Ciebie. W przypadku innych języków interpretowanych, takich jak python czy bash, nie musisz zostawiać plików spacemac, aby ich używać. Mają nawet sposób na uruchamianie bloków kodu bezpośrednio w tekście, który działa fantastycznie w przypadku programowania literackiego lub programowania odtwarzalnego, w którym kod i dane znajdują się w tym samym pliku. Oba wykonane jako tekst.

Spacemacs jest znacznie cięższy w początkowym ładowaniu, ale dodatkowe rzeczy, które możesz z nim zrobić, są warte kilku sekund kosztów uruchomienia. Warto to sprawdzić w trybie organizacji z jedną warstwą. Jest to najlepszy konspekt, programator, dziennik / lista rzeczy do zrobienia, z jakiego kiedykolwiek korzystałem.

C. Kelly Osborn
źródło
0

Udać się

  1. Narzędzie godoctor ( github ) obsługuje kilka funkcji refaktoryzacji
  • Przemianować
  • Wyodrębnij funkcję
  • Wyodrębnij zmienną lokalną
  • Przełącz var ⇔: =
  • Dodaj odcinki Godoc

Istnieje wtyczka vim https://github.com/godoctor/godoctor.vim, która udostępnia je

Z kursorem do zmiany nazwy:

:Rename <newname>

Podświetlany blok do wyodrębnienia:

:Refactor extract newfunc
  1. vim-go

    • Dokładna bezpieczna dla typu zmiana nazwy identyfikatorów za pomocą :GoRename.
  2. Serwer językowy gopls

Hotschke
źródło