Eu gostaria de otimizar meu fluxo de trabalho "localizar e substituir" no Vim. É algo que faço frequentemente, como tenho certeza que a maioria de vocês também. Geralmente algo como - copie um bloco e mude o nome de uma variável em alguns lugares. Eu sei, eu sei, que provavelmente dispara o reflexo "por que você está copiando e colando código", mas não vamos seguir esse caminho ... Existem muitos casos de uso válidos :)
Conheço bem os comandos de pesquisa e substituição: :s
ou :%s
mas não gosto deles. Obriga-me a digitar o nome completo da variável que estou procurando e para o que estou mudando. Talvez exista uma maneira melhor de corrigir a quantidade de digitação :%s
? Costumo usar nomes de variáveis descritivos longos, de modo que isso é realmente um diferencial para mim. Eu também não gosto de como digitar um nome de variável a partir do zero é propenso a erros de digitação e pode consumir tempo e inteligência para caçar erros de digitação. Eu prefiro digitá-lo uma vez e depois copiar e colar para evitar isso inteiramente, se possível.
Meu fluxo de trabalho atual usa alguma combinação de movimento / puxar / selecionar / pesquisar / colocar para mover o arquivo e substituir um por um. Não é ótimo, mas tem o benefício de evitar a digitação de nomes de variáveis completos. Talvez eu precise digitar as primeiras letras com /
ou usar outro comando de movimento (por exemplo fx
), dependendo do que estiver ao redor, e pressione ve
a tecla para selecionar a palavra inteira. Também não me importo de ter que repetir para cada instância. Eu nunca faço uma busca completa substituir sem confirmar cada alteração. Mas seria muito preferível se eu pudesse repetir a ação de substituição com um único pressionamento de tecla (o que não posso fazer com esse método). cada substituição é geralmente algo como n
, em seguida, ve
em seguida, p
(ou pior "0p
)
Existe uma maneira mais rápida?
fonte
.
repete o último "bloco de comando" (não tem certeza do termo exato. por exemplo: mover + ação + texto. por exemplo:cwtoto<Esc>
(mude do cursor para o final da palavra com "toto"))c/foo<enter>bar<Esc>
(mude do cursor para pouco antes " foo "e substitua por" bar "). Você pode mover (com cursor, hjkl ou um número + hjkl (faz isso n vezes), G (ir para o final do arquivo) / algo (ir logo antes" algo "), etc) e pressione.
para refazer o mesmo 'bloco de comando'n
ve
"0p
. Que, infelizmente, não pode ser replicado com apenas um.
n ce ctrl-r 0 <esc> n.n.n.n.n.n.
Respostas:
Na verdade, eu tenho um fluxo de trabalho bastante semelhante ao seu (copiar e colar blocos que são semelhantes e depois usar
:s
para alterar nomes de variáveis), especialmente quando estou escrevendo muitas linhas semelhantes, exceto pela variável que elas usam. Mas há algumas coisas que faço que você pode achar úteis.Coisas gerais do vim
A primeira coisa que o ajudará é perceber que
:s//foo/g
preencherá o termo de pesquisa que você usou por último e o substituirá por foo . Só isso pode economizar muito tempo, mas quando você o combina com o comando asterisco (procure a palavra sob o cursor atual), ele economiza muito tempo. Por exemplo, para mudar tudofoo
paraspam
, em vez de fazerO que exige que você digite foo e spam (que podem ser variáveis longas), você pode simplesmente navegar para foo e fazer:
Dessa forma, você pode obter rapidamente o nome da variável que está alterando pesquisando-a e não precisará digitá-la. Isso também funcionará bem com o seu fluxo de trabalho atual de usar
n
muito. Também é útil terhlsearch
, porque então você pode dizer visualmente onde estão as variáveis que você está substituindo.(nota: O comando asterisco irá adicionar limites de palavra, que é
\<
e\>
em torno da palavra sob o cursor Se você não quer isso, use.g*
em vez disso.)Você pode usar
@:
para refazer o último comando substituto. Isso é bom se você deseja executar um:s
comando em várias linhas, mas nem todas elas:%s
não funcionarão. Outra opção é a bandeira de confirmação, ou seja:%s///gc
. Isso permitirá que você digitey
oun
em cada ocorrência para decidir se deseja substituí-lo ou não.Como Desty apontou , você também pode &executar novamente o último comando substituto, mas observe que isso não manterá seus sinalizadores (como
global
ouconfirm
). Se isso é bom ou ruim, depende da sua opinião pessoal. Se você gostaria de usar isso, mas manter suas bandeiras também, você pode fazerSe você deseja alterar todas as ocorrências em um bloco, mas não todas as correspondências no arquivo, você sempre pode usar uma seleção visual do bloco, que será preenchida
ao seu substituto, que o restringe às linhas que você selecionou. Quando combinado com a abordagem de asterisco, acho isso extremamente útil. Além disso, se você estiver criando vários comandos substitutos no mesmo bloco de linhas, poderá usar gvpara selecionar novamente as mesmas linhas para executar outro comando. (seja
:substitute
um comando normal ou)Se você executar outro comando substituto, não precisará selecionar novamente as mesmas linhas, porque
:'<,'>
ainda operará nas mesmas linhas. No entanto, é mais conveniente digitarao invés de
Plugins / Mapeamentos que eu gosto
Eu tenho o seguinte mapeamento na minha
.vimrc
que estende a abordagem asterisco para que eu só precisa digitar o novo nome desejado:Para usar isso, basta colocar o cursor na palavra que deseja alterar e digitar
<leader>rNewVarName<cr>
e pronto. Observe que isso substituirá todas as correspondências sem oferecer a opção de confirmá-las; portanto, você pode não gostar muito. Claro, você pode simplesmente mudar paraPara permitir a opção de confirmação.
editar : Após a resposta da missa e o comentário da rcorre , você também pode escrever isso como
Qual tem a vantagem de manter o seu registro sem nome o mesmo.
Se você estiver renomeando grupos de variáveis semelhantes ao mesmo tempo, por exemplo, alterando
para
pode ser difícil substituir todos eles individualmente. É aqui que o tpope / vim-abolish é útil. Você pode substituir tudo isso em um comando por:
e cuida da capitalização para você.
Isso deve ajudá-lo muito, mas deixe-me saber se há algo sobre essas abordagens que você não gosta ou sente que está faltando. Fico feliz em falar sobre mais abordagens. :)
Leitura recomendada:
:h s_c
:h *
:h g*
:h @:
:h /\<
:h &
fonte
<leader>rc
(oucr
) adicioná/c
-la ao final. Além disso, euset gdefault
configurei, porque quase nunca quero substituir um único resultado, então seria apenasyiw:%s/\<<C-r>"\>//<left><left>
ctrl+r-ctrl+w
no mapeamento (como sugerido por @Mass) ele deve funcionar o mesmo, mas não vai mexer com o seu registo puxão (que pode ou não ser desejável).
para realizar substituições adicionais.A
c_CTRL-R
família de mapas pode melhorar bastante o seu fluxo de trabalho:Você não precisa digitar nomes de variáveis ao usar
:s/
, basta usarCTRL-R
CTRL-W
para inserir a palavra sob o cursor na linha de comando (ressalva: isso não escapa caracteres especiais, como*
faz).Depois de fazer uma pequena alteração usando
ce
, você pode procurar a palavra antiga usando/
CTRL-R
-
. Em seguida, use.
para repetir a alteração.Se você precisar fazer alterações no padrão de pesquisa
CTRL-R
/
, colocará a pesquisa existente na linha de comando.Finalmente, você pode colocar o conteúdo de qualquer registro usando
CTRL-R
{register}
fonte
Ctrl-R
/
? Eu uso isso com bastante frequência em:s
comandos se quiser usar um termo de pesquisa que seja quase mas não exatamente o mesmo que o anterior.Existem mais alguns métodos que (para minha surpresa!) Ainda não foram mencionados.
Usando o
gn
comandognfunciona como o ncomando, exceto que, além de pular para a partida, entra no modo visual, com toda a partida selecionada.
Portanto, para alterar uma palavra (ou qualquer coisa que você possa corresponder a uma expressão regular!), Procure-a primeiro 1 e, em seguida, pressione cgnseguido do texto com o qual deseja substituir a correspondência e Escretornar ao modo normal.
(Você menciona que, às vezes, o texto de substituição que você deseja usar é armazenado no
"0
registro yank - observe que você pode inseri-lo rapidamente sem precisar redigitá-lo pressionando Ctrl+R0no modo de inserção.)Você pode então pular para a próxima partida e repetir a alteração com um único .toque de tecla!
Se houver lugares onde você não deseja fazer a substituição, basta pressionar unpara desfazer a alteração e pular para a próxima partida.
1: Rapidamente, usando as outras sugestões sobre esta página, como *, Ctrl+RCtrl+W, etc. Veja também o comentário de Peter Rincker para mais sugestões sobre como preencher inicialmente a sua pesquisa.
Usando o Modo de Seleção
(Aprendi isso com romainl 's post sobre o subreddit vim . Eu não sei se ele inventou isso sozinho ou estava apenas passando-o.)
O modo de seleção é um pouco semelhante ao modo visual, exceto se você começar a digitar o texto selecionado e imediatamente substituído pelo que você digita (como o modo de seleção funciona na maioria dos outros editores).
Assim, você pode usar esse trio de mapeamentos para fazer uma localização / substituição muito rápida, que pode ser alterada no meio do arquivo, se necessário:
Mapeamento do modo normal : entra no modo de seleção com a palavra mais próxima do cursor selecionado.
Você pode digitar sua substituição para a palavra selecionada e ( sem pressionar Esc) usar o:
Inserir mapeamento do modo : Salta para a próxima correspondência e entra no modo de seleção.
Você pode digitar uma nova substituição ou pressionar .para usar o:
Mapeamento do modo de seleção : reinsere o último texto inserido - essencialmente, repete a última inserção.
fonte
gn
método no final da minha resposta ontem vi.stackexchange.com/a/13696/488 ontem pelo que vale a pena! Sua resposta tem uma formatação muito melhor.gn
uma vez), e é o método específico (e não apenas ogn
comando) que me surpreendeu ainda não ter sido mencionado.gn
. Oferece mais opções de pesquisa. Pobre homem é mapeamento estrela visualxnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr><cr>
. Episódio relacionado do Vimcasts: Operando em correspondências de pesquisa usando o gnO plug-in https://github.com/terryma/vim-multiple-cursors cuida desse problema em sua maior parte.
Meu fluxo de trabalho geralmente é o seguinte:
ctrl-n
até que tudo esteja selecionado.c
e comece a digitar a substituição.O mais conveniente aqui é que você também pode executar operações mais complicadas do que apenas substituir a pesquisa, embora eu ache que, se você levar isso longe demais, o plug-in começará a mostrar algumas falhas.
fonte
Outra maneira de fazer coisas que ainda não foram mencionadas: Você pode usar a janela da linha de comando (aberta
q:
no modo normal - veja:help q:
para obter mais informações), na qual você tem acesso total aos recursos de preenchimento automático do Vim (i_CTRL-N
/i_CTRL-P
e as váriasi_CTRL-X
seqüências estar entre eles).Na janela da linha de comando, você também pode usar comandos no modo normal para editar a linha de comando, o que, por exemplo, significa que você pode puxar e colar partes dos comandos anteriores no histórico da linha de comando.
Observe que o cursor será movido para a janela da linha de comando ao usá-lo, o que significa que
CTRL-R CTRL-W
métodos semelhantes que envolvem a inserção de texto sob o cursor não funcionarão lá, ao contrário da linha de comando normal.fonte
:substitute
comando pressionando<ctrl-f>
A solução para isso está entre as outras respostas para mim:
Digamos que você tenha 6 linhas idênticas e queira substituir 'apple' nas duas do meio:
O que eu faço é:
v
para entrar no modo visual2j
:s/<C-R><C-W>/
que usa a seleção visual como o intervalo para:s
e depois insere a palavra sob o cursor<C-F>
que coloca você em um modo em que você pode editar seu comando como se fosse um buffer. Assim, você pode usar qualquer conclusão ou plug-in que desejar escolher a palavra de substituição e pronto.Tudo em uma linha, o fluxo para isso seria,
/apples<CR>2nv/apples<CR>nn:s/<C-R><C-W/oranges<CR>
mas parece pior do que é.No seu caso, você pode anexar o
/c
ao:s
comando para ignorar os que você não quer, se o intervalo contém alguns que você quiser pular::s/<C-R><C-W/orange/c
.Alternativamente (e talvez de forma mais simples), você poderia procurar por toda a palavra que você deseja substituir,
c
hange-lo, em seguida,gn
e.
para repetir a pesquisa e aplicar a mesma alteração novamente. Parece/\<apple\><CR>viwcorange<ESC>gn.gn.gn..ngn.
repeti-lo em três, pular uma instância e repeti-la uma última vez.fonte
vim -Nu NONE
). Apenas apita quando pressiono o primeiro.
. Alguma idéia do porquê disso? Em qualquer caso, seria mais simples de usarciw
, em vez deviw
en
em vez degn
fazer alterações neste caminho.Isso não está totalmente relacionado à questão, mas ainda deve ajudar a selecionar a palavra a ser substituída.
A pesquisa incremental (
set incsearch
) permite digitar o prefixo da palavra que você precisa encontrar, e o vim salta automaticamente para a primeira ocorrência do prefixo à medida que você digita cada vez mais. A pesquisa será confirmada se você pressionar Enter e descartado em Esc (no último caso, o cursor voltará para onde estava antes da pesquisa começar).No entanto, a pesquisa incremental fornece mais um recurso útil. Quando você já digitou o prefixo de uma palavra e o cursor está na posição correta, pressione
<C-L>
para adicionar caracteres da palavra sob o cursor à string de pesquisa. Isso permite que você insira a sequência substituída quase sem pressionar as teclas.Então, se eu quiser substituir
someOddVariableName
porevenOdderVariableName
, eu/someOddV
e chegue à ocorrência desomeOddVariableName
;<C-L>
atésomeOddVariableName
aparecer completamente na linha de pesquisa;:%s//evenOdderVariableName/g
ou qualquer comando de substituição necessário; você pode seguir outras respostas aqui.fonte
Você pode colocar o nome da variável no buffer primeiro (
yw
para copiar uma palavra) e, em seguida, copie e cole-o:%s
pressionando<C-r>"
.fonte
Se você deseja substituir uma variável dentro do novo bloco (colado), tenho duas sugestões:
Substituição automática
Vá para a primeira linha do novo bloco, pressione
ma
. Isso está marcando um local e nomeando-oa
.Vá para a última linha do novo bloco, pressione
mb
. Agora você tem dois locais nomeados.Agora substitua entre as duas linhas, assim:
:'a,'bs/oldVarName/newVarName/g
.Ou seja, o escopo da substituição está entre suas duas marcas.
A maneira manual
Vá para a primeira linha do novo bloco.
Use
/oldVarName
para encontrar a primeira instância deoldVarName
.Altere da seguinte forma:,
cwnewVarName<Esc>
que mudará a palavra paranewVarName
e pressionando escape.Use
n
para ir para a próxima instância deoldVarName
.Use
.
para repetir a última alteração (ou seja, repete issocw
).fonte
Muitas das outras respostas aqui já abordam as formas criadas para melhorar o fluxo de trabalho de localização e substituição, mas eu queria mencionar o abolish.vim , um plugin de Tim Pope. Faz substituições nas quais você deseja cobrir uma variedade maior de casos, normalmente causada por variações de caso ou porque precisa lidar com as formas singular e plural de uma palavra.
:S/child{,ren}/adult{,s}/g
converte corretamentechild
paraadult
,Children
paraAdults
eCHILD
paraADULT
.Se você estiver lidando com palavras com camelo, precisará incluir as letras maiúsculas nas palavras original e de substituição.
%:S/wordWrap/textBreak/g
lida corretamente com amboswordWrap
ewordwrap
.fonte
Como outros já apontaram, se você tiver o cursor posicionado sobre sua palavra, poderá usar a família de comandos Ctrl + r, sendo Ctrl + r Ctrl + w provavelmente o mais adequado para uso.
Esse método, no entanto, funciona apenas para inserir uma palavra (a logo abaixo do cursor), mas e se houver várias partes do texto no buffer que queremos usar? Como você não pode mover o cursor enquanto estiver na linha de comando. A melhor maneira de fazer isso é copiar partes do texto necessárias em diferentes registros, o que pode ser feito com o prefixo "{reg_letter} (aspas e a letra do registro) no operador de cópia. Dessa forma, será possível insira várias palavras na linha de comando posteriormente com Ctrl + r {reg_letter} .Isso é um pouco estranho, mas funciona.
Mas voltando à idéia anterior, seria ótimo se movermos a posição do cursor sobre o buffer enquanto escrevíamos um padrão. Dessa forma, poderíamos "escolher" o texto de diferentes posições com Ctrl + r Ctrl + w, então criei um plug-in que faz exatamente isso: EXtend.vim O plug-in também possui muitos outros recursos para realizar operações de substituição.
fonte