Refactoring in Vim


99

Ovviamente il fatto che tu possa effettuare il refactoring sugli IDE non ha prezzo per molti, non lo faccio quasi mai quando sto codificando ma potrei provare a farlo quando modifico la fonte di qualcun altro. Come si esegue un'attività così banale su più file in Vim?

Ho trovato questo plugin per il refactoring di Ruby, ma che ne dici di "qualsiasi" lingua?


2
Il refactoring è molto specifico della lingua. Devi cercare componenti aggiuntivi specifici per ogni lingua che ti interessa. Presumibilmente troverai componenti aggiuntivi per alcuni e non per altri. Se ce n'è uno che vuoi e non riesci a trovare, se ti senti ambizioso, potresti provare a scriverne uno, utilizzando un componente aggiuntivo esistente per un'altra lingua simile come punto di partenza.
Steve Jorgensen

2
VIM è progettato per modificare singoli file e forse file in una directory, non progetti . Molti refactoring supportati da IDE avranno un impatto sui file dell'intero progetto (ad esempio, rinominare una classe). Penso che sarebbe difficile farlo "bene" con un editor come (g) VI (m), al punto in cui penso che una società o un grande progetto dovrebbe assumersene. Fondamentalmente dovrebbero analizzare ogni lingua per evitare di fare semplici sostituzioni di stringhe e diventare inclini a errori (ctags fornisce un po ' di questo), così come i tipi di progetto corrispondenti (per sapere quali file modificare).
Merlyn Morgan-Graham,

1
Grazie per i commenti, penso che sia qui che le cose iniziano a diventare complicate e cercare di piegare VIM a un IDE non è una soluzione elegante per utilizzare un solo programma per modificare più lingue. Non voglio davvero rinunciare a VIM a causa di alcune delle funzionalità "avanzate" disponibili sugli IDE.
Helmut Granda,

@ MerlynMorgan-Graham - Alcune persone conservano il proprio codice in pochi file (grandi, che possono essere). Evita del tutto questo problema.
Rook

7
@ldigas: questo aggirerebbe il problema. Ma è abbastanza contro le pratiche consigliate per alcuni linguaggi (ad esempio Java). Fondamentalmente il codice si piega per adattarsi alle esigenze dello strumento, quando in realtà dovrebbe essere il contrario.
Merlyn Morgan-Graham

Risposte:


78

Sono d'accordo con il paradigma "Vim non è un IDE". Ma ci sono momenti in cui non c'è un IDE. Ecco cosa uso in quelle situazioni:

: grep,: vimgrep,: Ag,: Ggrep

Refactoring che ha più a che fare con le sostituzioni regolari che di solito uso : grep nel mio albero del progetto e quindi registro una macro per eseguire il refactoring -: ge: s non sono cervelli. Di solito mi consente di modificare rapidamente un gran numero di file con uno sforzo minimo. Onestamente, utilizzo questo metodo più di ogni altro.

A seconda del flusso di lavoro, i comandi integrati potrebbero essere lenti / scomodi. Se usi git, allora vorrai usare l'eccellente plugin Fugitive e il suo :Ggrepcomando per cercare solo i file archiviati in git. Mi piace anche Silver Searcher per la sua velocità.

: argdo,: cdo e: bufdo

: cdo e : argdo sono utili per eseguire comandi vim su un insieme di file.

riga di comando

Quando è più difficile determinare l'elenco dei file che necessitano di modifiche tramite, :vimgrepricorro ai comandi grep / find della riga di comando per curare più da vicino l'elenco dei file che ho bisogno di refactoring. Salvare l'elenco in un file di testo e utilizzare :ee un mashup di registrazioni di macro per apportare le modifiche necessarie.

Trovo che meno arrugginito mantengo le mie capacità di registrazione macro, più utile trovo Vim per il refactoring: sentirsi a mio agio nel salvare / ripristinare dai registri, aumentare / diminuire le variabili del contatore di registro, pulire / salvare le registrazioni macro su file per un uso successivo, ecc.


Aggiornare

Da quando ho scritto questo più videocast per i metodi che descrivo sono stati pubblicati su vimcasts.org (ti incoraggio a guardare TUTTI i Vimcast! ). Per il refactoring guarda questi:

Vimgolf è anche un ottimo modo per esercitarsi.

L'ubiquità dei server Language Server Protocol da quando ho scritto questa risposta ha anche portato alcune capacità di refactoring a Vim (e ad altri editor). IMO sono molto lontani dall'uguaglianza delle capacità di refactoring che vedresti in un IDE appositamente costruito (io li uso e preferisco coc e ALE). Vedi altre risposte su questa domanda per maggiori informazioni!


12
Il refactoring è MOLTO più del pattern matching, ecco perché gli IDE sono necessari per automatizzarlo in modo sicuro. Ovviamente, puoi farlo manualmente, ma considerando le opzioni disponibili e che la maggior parte delle volte è più sicuro farlo manualmente, perché dovresti prendere in considerazione qualsiasi altra opzione?
Cutberto Ocampo

1
@CutbertoOcampo Sono d'accordo con te in una certa misura: a seconda di una miriade di aspetti di un progetto (struttura, lingua (e), competenze e risorse del personale, solo per citarne alcuni), potrebbe esserci un ottimo strumento di refactoring applicabile al tuo problema. La mia risposta si applica a situazioni in cui ciò non è vero e tu vuoi affrontare il problema in Vim.
dsummersl

2
va bene, capisco che le persone potrebbero sentirsi più a loro agio nel fare le cose usando i loro strumenti preferiti da lungo tempo e che ci sono alcuni hack che possono funzionare davvero bene, probabilmente meglio di qualsiasi IDE là fuori, ma per un fuori dal comune -box soluzione Direi che un IDE effettivo avrebbe prestazioni migliori per la maggior parte degli utenti. Penserei a una situazione dell'80-20% (anche di più, con l'equilibrio a favore dell'IDE).
Cutberto Ocampo

1
C'è un ide per praticamente ogni lingua. Cercare di refactoring con vim o regex sembra assolutamente folle. Perché dovresti provare?
rotoli

1
@rolls per essere abbastanza potente da afferrare la macchina bisognosa di un collega casuale con non-tuo-ide o qualsiasi altro cfg con cui puoi solo convivere e lasciare una buona impressione in giro (non per "solo impressione" ma per reputazione e posizione futura).
sanguinoso

24

Language Server Protocol (LSP)

Il protocollo del server del linguaggio contiene la funzione per rinominare in modo intelligente i simboli in un progetto:

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

Ad esempio, il seguente language server supporta questo:

Puoi trovare più server di lingua sotto https://langserver.org/ .

Vim

È necessario un client editor di vim per utilizzarli all'interno di vim. Esistono le seguenti opzioni:

  1. LanguageClient-neovim (richiede rust) suggerisce la mappatura:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (richiede node.js) suggerisce la mappatura:

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

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

    Ale non definisce alcuna associazione di tasti. Questo deve essere fatto dall'utente.

  4. vim-lsp fornisce il seguente comando

    :LspRename
    

    Simile ad Ale non è suggerita alcuna mappatura. Tuttavia, ovviamente puoi definirne uno come segue

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

    ( <leader>rdeve essere sostituito dalla tua scelta; non ne conosco uno su cui la maggior parte dei plugin è d'accordo)

  5. vim-lsc ha una mappatura predefinita:

    'Rename': 'gR'
    

Vedi anche YouCompleteMe che facilita anche gli LSP.

Neovim

Neovim ha il supporto integrato iniziale per lsp dal 13.11.2019

Per le configurazioni comuni degli LSP, vedere https://github.com/neovim/nvim-lsp

Tuttavia, non sono riuscito a capire come funziona la ridenominazione intelligente. Se qualcuno lo sa, aggiorna questa sezione.

Altri refactoring

Non so se ci sono piani per il protocollo LSP per supportare refactoring più complessi, come la modifica della struttura della classe, l'aggiunta di parametri a metodi / funzioni o lo spostamento di un metodo in una classe diversa. Per un elenco di refactoring, vedere https://refactoring.com/catalog/ .


Sfortunatamente, il supporto per il refactoring nell'LSP è attualmente piuttosto debole rispetto allo stato dell'arte. github.com/Microsoft/language-server-protocol/issues/61
Mickael

AFAIK che rinominare per coc-renamefunziona solo sul buffer corrente. Non ha aggiornato l'uso del nome esportato a livello globale nel progetto (tra i file).
oligofren

16

Pitone

Per il linguaggio Python i seguenti plug-in forniscono funzionalità di ridenominazione "intelligenti" per vim:

  • jedi-vim( GitHub )<leader>r
  • ropevim( GitHub )CTRL-c r r
  • python-mode( GitHub ):h pymode-rope-refactoring

13

C-Family

  1. Prova il plugin Clighter per rinominare-refactoring per la famiglia c. È basato su clang, ma ci sono limitazioni e il plugin è contrassegnato come deprecato.

    La mappatura suggerita da Clighter è

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

    Nota, il plug-in successore clighter8 ha rimosso la funzionalità di ridenominazione nel commit 24927db42 .

  2. Se usi neovim, puoi dare un'occhiata al plug-in clamp . Suggerisce

     nmap <silent> <Leader>r :call ClampRename()<CR>
    

5

Ho scritto questo plugin per il refactoring generico. Richiede ancora molti miglioramenti. In futuro cercherò di abbandonare i ctags a favore del clang per i refactoring di C e C ++.


4

Forse non è la soluzione più elegante, ma l'ho trovata molto utile: utilizzo ECLIM per collegare VIM ed Eclipse. Ovviamente tutte le modifiche al codice sorgente vengono eseguite in VIM, ma quando è il momento di effettuare il refactoring, è possibile sfruttare le capacità superiori di Eclipse in questa materia.

Provaci.


4

Plugin YouCompleteMe (YCM) (20k stelle su GitHub)

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

:h RefactorRename-new-name

Nei tipi di file supportati, questo comando tenta di eseguire una ridenominazione semantica dell'identificatore sotto il cursore. Ciò include la ridenominazione di dichiarazioni, definizioni e usi dell'identificatore o qualsiasi altra azione appropriata per la lingua. Il comportamento specifico è definito dal motore semantico in uso.

Simile a FixIt, questo comando applica modifiche automatiche ai file di origine. Le operazioni di ridenominazione possono comportare modifiche a più file, che possono essere aperti o meno nei buffer di Vim in quel momento. YouCompleteMe gestisce tutto questo per te. Il comportamento è descritto nella sezione seguente.

Supportato nei tipi di file: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs

Per impostazione predefinita non esiste alcuna mappatura.


Quindi per ora funziona solo per javascript, dattiloscritto e java?
SR

3

Plugin Factorus

C'è un altro plugin vim dedicato per il refactoring chiamato factorus che è disponibile su GitHub .

Attualmente (2017-12), supporta le lingue

  • c,
  • java e
  • pitone.

2

Posizionare il cursore sul nome per eseguire il refactoring e digitare

gd(o gDse stai rifattorizzando una variabile globale).

Poi

cgn nuovo nome esc

e

. una o più volte per eseguire il refactoring delle occorrenze successive

o

:%norm . per eseguire il refactoring di tutte le occorrenze nel buffer contemporaneamente.


1

Scrivo molto codice C / C ++ in vim. Il refactoring più comune che faccio è rinominare variabili, nomi di classi, ecc. Di solito, utilizzo :bufdo :%s/source/dest/gper eseguire una ricerca / sostituzione nei file, che è quasi la stessa della ridenominazione fornita dai grandi IDE.
Tuttavia, nel mio caso, ho scoperto che di solito rinomino entità simili, scritte in casi diversi (ad esempio CamelCase, snake_case, ecc.), Quindi ho deciso di scrivere una piccola utility per aiutare con questo tipo di ricerca "smart-case" / sostituire, è ospitato qui . È un'utilità della riga di comando, non un plug-in per vim, spero che tu possa trovarlo utile.


0

Per il refactoring, se stai usando Unite (e dovresti), puoi quindi usare vim-qfreplace e renderlo estremamente semplice. Guarda questo video che mostra come funziona. Una volta impostato il flusso di lavoro, puoi creare alcune mappature per ottimizzarlo (invece di digitare la maggior parte delle cose come nel video).


0

Una combinazione di due plugin: vim-ripgrep , per trovare tra i file e mettere i risultati nella finestra quickfix, e quickfix-reflector per salvare le modifiche direttamente nella finestra quickfix e fare in modo che salvi automaticamente ogni modifica nei file.


0

Considererei l'utilizzo della versione spacemacs di emacs. Utilizza le stesse modalità e la maggior parte delle sequenze di tasti di Vim ma ha molti altri componenti aggiuntivi a causa della sua natura lenta. Se vuoi programmare in C ++ devi solo aggiungere il livello c ++ e la maggior parte dell'IDE è già configurata per te. Per altri linguaggi interpretati come python o bash non è necessario lasciare spacemacs per usarli. Hanno anche un modo per eseguire blocchi di codice direttamente all'interno del testo che funziona in modo fantastico per la programmazione alfabetizzata o la programmazione riproducibile in cui il codice ei dati sono nello stesso file. Entrambi fatti come testo.

Spacemacs è molto più pesante nel suo caricamento iniziale, ma le cose aggiuntive che puoi fare con esso valgono i pochi secondi di costo di avvio. Vale la pena dare un'occhiata alla modalità organizzazione a un livello. È il miglior outliner, programmatore, timer giornaliero / elenco di cose da fare che abbia mai usato.


0

Partire

  1. Lo strumento godoctor ( github ) supporta diverse funzionalità di refactoring
  • Rinominare
  • Funzione di estrazione
  • Estrai variabile locale
  • Attiva / disattiva var ⇔: =
  • Aggiungi Godoc stub

C'è un plugin vim https://github.com/godoctor/godoctor.vim che li rende disponibili

Con il cursore nella cosa da rinominare:

:Rename <newname>

Blocco di evidenziazione da estrarre:

:Refactor extract newfunc
  1. vim-go

    • Ridenominazione precisa degli identificatori in base ai tipi con :GoRename.
  2. Server linguistico gopls

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.