Refatoração no Vim

98

É claro que o fato de você poder refatorar em IDEs não tem preço para muitos. Quase nunca faço isso quando estou codificando, mas posso tentar fazer isso ao editar o código-fonte de outra pessoa. Como você realiza uma tarefa tão trivial em vários arquivos no Vim?

Eu encontrei este plugin para refatorar Ruby, mas que tal "qualquer" linguagem?

Helmut Granda
fonte
2
A refatoração é muito específica da linguagem. Você precisa procurar add-ons específicos para cada idioma no qual está interessado. Você provavelmente encontrará add-ons para alguns e não para outros. Se houver um que você deseja e não consegue encontrar, se estiver se sentindo ambicioso, tente escrever um, usando um add-on existente para outra linguagem semelhante como ponto de partida.
Steve Jorgensen
2
O VIM foi projetado para editar arquivos individuais, e talvez arquivos em um diretório - não projetos . Muitas refatorações suportadas por IDE impactarão os arquivos em todo o projeto (por exemplo, renomear uma classe). Acho que seria complicado fazer isso "direito" com um editor como (g) VI (m), a ponto de pensar que uma empresa ou um grande projeto teria que assumir. Eles basicamente teriam que analisar cada idioma para evitar fazer substituições de strings simples e se tornarem propensos a erros (ctags fornece alguns deles ), bem como os tipos de projeto correspondentes (para saber quais arquivos editar).
Merlyn Morgan-Graham
1
Obrigado pelos comentários, acho que é aqui que as coisas começam a ficar complicadas e tentar transformar o VIM em um IDE não é uma solução elegante para usar apenas um programa para editar vários idiomas. Eu realmente não quero desistir do VIM devido a alguns dos recursos "avançados" disponíveis nos IDEs.
Helmut Granda
@ MerlynMorgan-Graham - Algumas pessoas apenas mantêm seu código em alguns arquivos (grandes, que podem ser). Evita esse problema completamente.
Torre
7
@ldigas: Isso resolveria o problema. Mas é totalmente contra as práticas recomendadas para algumas linguagens (por exemplo, Java). Basicamente, o código se flexiona para se adequar às necessidades da ferramenta, quando na verdade deveria ser o contrário.
Merlyn Morgan-Graham

Respostas:

76

Eu concordo com o paradigma 'Vim não é um IDE'. Mas às vezes não há um IDE. Aqui está o que eu uso nessas situações:

: grep,: vimgrep,: Ag,: Ggrep

Refatoração que tem mais a ver com substituições regulares que eu geralmente uso : grep na minha árvore de projeto e, em seguida, registro uma macro para fazer a refatoração -: ge: s não são brainers. Normalmente, ele permite que eu modifique rapidamente um grande número de arquivos com muito pouco esforço. Honestamente, eu uso esse método mais do que qualquer outro.

Dependendo do seu fluxo de trabalho, os comandos integrados podem ser lentos / inconvenientes. Se você usa git, então você vai querer usar o excelente plugin Fugitive e seu :Ggrepcomando para pesquisar apenas arquivos registrados no git. Também gosto do Silver Searcher por sua rapidez.

: argdo,: cdo e: bufdo

: cdo e : argdo são úteis para executar comandos do vim em um conjunto de arquivos.

linha de comando

Quando é mais difícil determinar a lista de arquivos que precisam de alterações por meio, :vimgrepeu recorro aos comandos grep / find da linha de comando para selecionar mais de perto a lista de arquivos que preciso refatorar. Salve a lista em um arquivo de texto e use :eum mashup de gravações de macro para fazer as alterações que preciso fazer.

Eu acho que quanto menos enferrujado mantenho minhas habilidades de gravação de macro, mais útil eu acho o Vim para refatoração: me sentindo confortável salvando / restaurando de registros, incrementando / diminuindo variáveis ​​de contador de registro, limpando / salvando gravações de macro em arquivo para uso posterior, etc.


Atualizar

Desde que escrevi este, mais videocasts para os métodos que descrevo foram publicados no vimcasts.org (eu encorajo você a assistir TODOS os Vimcasts! ). Para refatoração, observe estes:

Vimgolf também é uma ótima maneira de praticar.

A onipresença dos servidores Language Server Protocol desde que escrevi esta resposta também trouxe alguma capacidade de refatoração para o Vim (e outros editores). IMO, eles estão muito longe de igualar a capacidade de refatorar recursos que você veria em um IDE construído para um propósito (eu os uso e prefiro COC e ALE). Veja outras respostas nesta questão para mais informações!

dsummersl
fonte
12
Refatorar é muito mais do que correspondência de padrões, é por isso que os IDEs são necessários para automatizar isso de maneira segura. Obviamente, você pode fazer manualmente, mas considerando as opções disponíveis, e que na maioria das vezes é mais seguro fazê-lo manualmente, por que você consideraria qualquer outra opção?
Cutberto Ocampo
1
@CutbertoOcampo Concordo com você até certo ponto: dependendo da miríade de aspectos de um projeto (estrutura, idioma (s), habilidades e recursos da equipe, para citar alguns), PODE haver uma ótima ferramenta de refatoração aplicável ao seu problema. Minha resposta se aplica a situações em que isso não é verdade e você deseja resolver o problema no Vim.
dsummersl
2
tudo bem, eu entendo que as pessoas podem se sentir mais confortáveis ​​fazendo coisas usando suas ferramentas preferidas de longa data, e que existem alguns hacks que podem funcionar muito bem, provavelmente melhor do que qualquer IDE por aí, mas para um fora do -box solution Eu diria que um IDE real teria um desempenho melhor para a maioria dos usuários. Eu estaria pensando em um tipo de situação de 80-20% (ainda mais, com o saldo a favor do IDE).
Cutberto Ocampo,
1
Existe uma ide para praticamente todos os idiomas. Tentar refatorar com vim ou regex parece absolutamente insano. Por que você tentaria?
rola
1
@rolls para ser potente o suficiente para agarrar a máquina em necessidade de um colega aleatório com não-seu-ide ou qualquer outra cfg com a qual você só possa conviver e deixar uma boa impressão por aí (não para "apenas impressão", mas para reputação e posição futura).
sangrento
23

Language Server Protocol (LSP)

O protocolo do servidor de linguagem contém o recurso para renomeação inteligente de símbolos em um projeto:

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

Por exemplo, o servidor de idioma a seguir oferece suporte para isso:

Você pode encontrar mais servidores de idiomas em https://langserver.org/ .

Vim

Um cliente de editor vim é necessário para usá-los dentro do vim. Existem as seguintes opções:

  1. LanguageClient-neovim (requer ferrugem) sugere o mapeamento:

    nnoremap <silent> <F2> :call LanguageClient_textDocument_rename()<CR>
    
  2. coc.nvim (requer node.js) sugere o mapeamento:

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

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

    Ale não define atalhos de teclado. Isso deve ser feito pelo usuário.

  4. vim-lsp fornece o seguinte comando

    :LspRename
    

    Semelhante ao Ale, nenhum mapeamento é sugerido. No entanto, é claro que você pode definir um da seguinte forma

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

    ( <leader>rdeve ser substituído por sua escolha; não conheço um com o qual a maioria dos plug-ins concorde)

  5. vim-lsc tem um mapeamento padrão:

    'Rename': 'gR'
    

Veja também YouCompleteMe, que também facilita os LSPs.

Neovim

Neovim tem suporte integrado inicial para lsp desde 13.11.2019

Consulte para configurações comuns de LSPs https://github.com/neovim/nvim-lsp

No entanto, não consegui descobrir como funciona a renomeação inteligente. Se alguém souber disso, atualize esta seção.

Outras Refatorações

Não sei se existem planos para o protocolo LSP suportar refatorações mais complexas, como alterar a estrutura de classe, adicionar parâmetros a métodos / funções ou mover um método para uma classe diferente. Para obter uma lista de refatorações, consulte https://refactoring.com/catalog/ .

Hotschke
fonte
Infelizmente, o suporte para refatoração no LSP é atualmente muito fraco em comparação com o estado da arte. github.com/Microsoft/language-server-protocol/issues/61
Mickael
AFAIK que renomear coc-renamesó funciona no buffer atual. Ele não atualizou o uso do nome exportado globalmente no projeto (entre arquivos).
oligofren
15

Pitão

Para a linguagem python , os seguintes plug-ins fornecem recursos de renomeação 'inteligentes' para o vim:

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

Família C

  1. Experimente o plugin Clighter para renomear-refatoração para a família c. É baseado no clang, mas existem limitações e o plugin está marcado como obsoleto.

    O mapeamento sugerido por Clighter é

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

    Observe, o plug-in sucessor clighter8 removeu a funcionalidade de renomeação no commit 24927db42 .

  2. Se você usa o neovim, pode dar uma olhada no grampo do plugin . Sugere

     nmap <silent> <Leader>r :call ClampRename()<CR>
    
BB Chung
fonte
5

Escrevi este plugin para refatoração genérica. Ainda requer muitas melhorias. Em algum momento no futuro, tentarei abandonar os ctags em favor do clang para refatorações de C e C ++.

Luc Hermitte
fonte
4

Talvez não seja a solução mais elegante, mas achei muito útil: eu uso ECLIM para conectar o VIM e o Eclipse. É claro que toda a edição do meu código-fonte é feita no VIM, mas quando é hora de refatorar, pode-se tirar vantagem das capacidades superiores do Eclipse neste assunto.

De uma chance.

fjrg76
fonte
3

Plugin Factorus

Existe outro plugin vim dedicado para refatoração chamado factorus que está disponível no github .

Atualmente (2017-12), ele suporta os idiomas

  • c,
  • java, e
  • Pitão.
Hotschke
fonte
3

Plugin YouCompleteMe (YCM) (20 mil estrelas no github)

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

:h RefactorRename-new-name

Em tipos de arquivo suportados, este comando tenta realizar uma renomeação semântica do identificador sob o cursor. Isso inclui renomear declarações, definições e usos do identificador ou qualquer outra ação apropriada ao idioma. O comportamento específico é definido pelo mecanismo semântico em uso.

Semelhante a FixIt, este comando aplica modificações automáticas aos arquivos de origem. As operações de renomeação podem envolver alterações em vários arquivos, que podem ou não estar abertos nos buffers do Vim no momento. YouCompleteMe cuida de tudo isso para você. O comportamento é descrito na seção a seguir.

Compatível com tipos de arquivos: c, cpp, objc, objcpp, cuda, java, javascript, typescript, rust, cs

Por padrão, não há mapeamento.

Hotschke
fonte
Então, por enquanto, isso funciona apenas para javascript, typescript e java?
SR
2

Coloque o cursor no nome para refatorar e digitar

gd(ou gDse você estiver refatorando uma variável global).

Então

cgn novo nome esc

e

. uma ou mais vezes para refatorar próxima (s) ocorrência (s)

ou

:%norm . para refatorar todas as ocorrências no buffer de uma vez.

Geremia
fonte
1

Eu escrevo muito código C / C ++ no vim. A refatoração mais comum que faço é renomear variáveis, nomes de classes, etc. Normalmente, costumo :bufdo :%s/source/dest/gfazer uma pesquisa / substituição em arquivos, o que é quase o mesmo que renomear fornecido por grandes IDE.
No entanto, no meu caso, descobri que geralmente renomeio entidades semelhantes, escritas em casos diferentes (ou seja, CamelCase, snake_case, etc.), então decidi escrever um pequeno utilitário para ajudar com esse tipo de pesquisa de "caso inteligente" / substitua, está hospedado aqui . É um utilitário de linha de comando, não um plug-in para o vim, espero que seja útil para você.

dkrikun
fonte
0

Para refatorar, se você estiver usando o Unite (e deveria), você pode usar o vim-qfreplace e torná-lo extremamente fácil. Confira este vídeo que demonstra como funciona. Depois que seu fluxo de trabalho estiver definido, você pode fazer alguns mapeamentos para otimizá-lo (em vez de digitar a maioria das coisas, como no vídeo).

BenC
fonte
0

Uma combinação de dois plug-ins: vim-ripgrep , para localizar arquivos e colocar os resultados na janela de correção rápida, e quickfix-reflector para salvar as alterações diretamente na janela de correção rápida e salvar automaticamente cada alteração nos arquivos.

Jason
fonte
0

Eu consideraria usar a versão spacemacs do emacs. Ele usa os mesmos modos e a maioria dos pressionamentos de tecla que o Vim, mas tem muitos outros add-on por causa de sua natureza lisp. Se você deseja programar em C ++, basta adicionar a camada C ++ e a maior parte do IDE já está configurada para você. Para outras linguagens interpretadas como python ou bash, você não precisa deixar o spacemacs para usá-los. Eles ainda têm uma maneira de executar blocos de código diretamente no seu texto, o que funciona de forma fantástica para programação literária ou reproduzível, onde o código e os dados estão no mesmo arquivo. Ambos feitos como texto.

O Spacemacs é muito mais pesado em sua carga inicial, mas as coisas adicionais que você pode fazer com ele valem os poucos segundos de custo inicial. Vale a pena conferir o modo org de uma camada. É o melhor delineador, programador, cronômetro diário / lista de tarefas que já usei.

C. Kelly Osborn
fonte
0

Ir

  1. A ferramenta godoctor ( github ) suporta vários recursos de refatoração
  • Renomear
  • Extrair Função
  • Extrair Variável Local
  • Alternar var ⇔: =
  • Adicionar esboços Godoc

Existe um plugin do vim https://github.com/godoctor/godoctor.vim que os torna disponíveis

Com o cursor posicionado para renomear:

:Rename <newname>

Bloco de realce para extrair:

:Refactor extract newfunc
  1. vim-go

    • Renomeação de identificadores com segurança de tipo precisa com :GoRename.
  2. Servidor de idioma gopls

Hotschke
fonte