Quando procuro com o /
comando do modo normal:
/\vSEARCHTERM
O Vim inicia a pesquisa a partir da posição do cursor e continua para baixo, indo até o topo. No entanto, quando procuro e substituo usando o :substitute
comando:
:%s/\vBEFORE/AFTER/gc
Em vez disso, o Vim começa no início do arquivo.
Existe uma maneira de fazer com que o Vim execute a pesquisa e substituição começando da posição do cursor e passando para o topo quando chega ao final?
\vpattern
- padrão 'muito mágico': caracteres não alfanuméricos são interpretados como símbolos regex especiais (nenhum escape é necessário)%
? não vejo nenhum uso razoável para que você esteja examinando todo o arquivo de qualquer maneira.Respostas:
1. Não é difícil alcançar o comportamento usando uma substituição em duas etapas:
Primeiro, o comando de substituição é executado para cada linha, começando da atual até o final do arquivo:
Em seguida, esse
:substitute
comando é repetido com o mesmo padrão de pesquisa, string de substituição e sinalizadores, usando o:&
comando (consulte:help :&
):O último, entretanto, realiza a substituição no intervalo de linhas da primeira linha do arquivo para a linha onde a marca de contexto anterior foi definida, menos um. Como o primeiro
:substitute
comando armazena a posição do cursor antes de iniciar as substituições reais, a linha endereçada por''
é a linha que era a atual antes que o comando de substituição fosse executado. (O''
endereço refere-se à'
pseudo-marca; consulte:help :range
e:help ''
para obter detalhes.)Observe que o segundo comando (após o
|
separador de comando - consulte:help :bar
) não requer nenhuma alteração quando o padrão ou sinalizadores são alterados no primeiro.2. Para economizar alguma digitação, a fim de trazer o esqueleto do comando de substituição acima na linha de comando, pode-se definir um mapeamento de modo normal, assim:
A
<c-b><right><right><right><right>
parte final é necessária para mover o cursor para o início da linha de comando (<c-b>
) e, em seguida, quatro caracteres para a direita (<right>
× 4), colocando-o entre os dois primeiros sinais de barra, pronto para o usuário começar a digitar o padrão de pesquisa . Assim que o padrão desejado e a substituição estiverem prontos, o comando resultante pode ser executado pressionando Enter.(Pode-se considerar ter em
//
vez de///
no mapeamento acima, se preferir digitar o padrão, então digite a barra separadora, seguida pela string de substituição, em vez de usar a seta para a direita para mover o cursor sobre uma barra separadora já presente começando a peça de reposição.)fonte
:noremap <leader>R :,$s///gc\|1,''-&&<c-b><right><right><right><right>
. Ele é:,$s///gc|1,''-&&
colocado na linha de comando com o cursor entre os dois primeiros sinais de barra. Depois de digitar o padrão e substituição desejados, você pode executar o comando resultante pressionando Enter .Você já está usando um intervalo,,
%
que é uma forma abreviada de1,$
significar o arquivo inteiro. Para ir da linha atual até o final que você usa.,$
. O período significa linha atual e$
significa a última linha. Portanto, o comando seria:Mas a
.
linha ou atual pode ser assumida, portanto, pode ser removida:Para obter mais ajuda, consulte
fonte
10:s/pattern/replace/gc
%
é um atalho para1,$
(ajuda do Vim =>
:help :%
igual a 1, $ (o arquivo inteiro).).
é a posição do cursor para que você possa fazerPara substituir do início do documento até o cursor
etc
Eu sugiro fortemente que você leia o manual sobre range,
:help range
pois quase todos os comandos funcionam com range.fonte
FINALMENTE encontrei uma solução para o fato de que sair da pesquisa volta ao início do arquivo sem escrever uma função enorme ...
Você não acreditaria quanto tempo demorei para inventar isso. Simplesmente adicione um prompt se deseja quebrar: se o usuário pressionar
q
novamente, não quebra. Então, basicamente, saia da pesquisa tocando emqq
vez deq
! (E se você quiser embrulhar, basta digitary
.)Na verdade, eu mapeei isso para uma tecla de atalho. Assim, por exemplo, se você deseja pesquisar e substituir todas as palavras sob o cursor, começando da posição atual, por
q*
:fonte
q
,l
ou Esc ) e não quiser continuar a partir do início, você já pode pressionarq
ou Esc novamente para sair do segundo comando imediatamente. Ou seja, a adição proposta do prompt parece duplicar efetivamente a funcionalidade já presente.yyyq
, continuar editando, sem saltos desorientadores. Masyyyqq
é quase tão bom, se você considerar um toque duplo, praticamente um único toque em termos de facilidade de uso.q
pela segunda vez). O último deixa o cursor na última ocorrência que foi substituída (logo antes de a primeiraq
ser pressionada).norm!``
comando::,$s/BEFORE/AFTER/gc|1,''-&&|norm!``
.Aqui está algo muito aproximado que aborda as preocupações sobre envolver a pesquisa com a abordagem de duas etapas (
:,$s/BEFORE/AFTER/gc|1,''-&&
) ou com um intermediário "Continuar no início do arquivo?" abordagem:Esta função usa alguns hacks para verificar se devemos passar para o topo:
fonte
Estou atrasado para a festa, mas confiei muito nessas respostas de stackoverflow atrasadas para não fazer isso. Reuni dicas sobre reddit e stackoverflow, e a melhor opção é usar o
\%>...c
padrão na pesquisa, que corresponde apenas após o cursor.Dito isso, ele também confunde o padrão para a próxima etapa de substituição e é difícil de digitar. Para combater esses efeitos, uma função personalizada deve filtrar o padrão de pesquisa posteriormente, redefinindo-o. Ver abaixo.
Eu me contentei com um mapeamento que substitui a próxima ocorrência e pula para a seguinte, e não mais (era meu objetivo de qualquer maneira). Tenho certeza de que, com base nisso, uma substituição global pode ser elaborada. Tenha em mente que ao trabalhar em uma solução que visa algo como
:%s/.../.../g
o padrão abaixo filtra as correspondências em todas as linhas à esquerda da posição do cursor - mas é limpo após a conclusão da única substituição, portanto, perde esse efeito logo após, pula para o próxima partida e, portanto, é capaz de percorrer todas as partidas uma a uma.fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
fonte