Padronize \ n e \ r na sintaxe de pesquisa / substituição do Vim

1

No Vim, um procura por novas linhas como \n , mas as novas linhas na cadeia de substituição devem ser inseridas como \r . Entendo que existem motivos para esse comportamento , mas, para os meus objetivos, acho irritante. Eu quero ser capaz de usar \n para significar (essencialmente) a mesma coisa em um padrão de pesquisa e em uma string de substituição: especificamente, em um padrão de pesquisa deve corresponder a novas linhas e em uma string de substituição deve inserir novas linhas.

Existe uma maneira de obter esse comportamento? Não acho que os remapeamentos simples funcionarão, já que o comando substituto precisa ser analisado para determinar se \n faz parte do padrão de pesquisa ou da sequência de substituição.

    
por Kyle Strand 17.04.2014 / 19:20

3 respostas

0

Resposta alternativa usando um plugin (esta é a solução que decidi usar, embora só funcione com o Vim 7.4 +):

Usando Vim Encantado , coloque let g:VeryMagicSubstituteNormalise = 1 no seu .vimrc .

(Este plugin usa o plugin CRDispatcher , que permite substituições de texto em comandos após o Enter key foi pressionada mas antes o comando é realmente executado. Portanto, nenhum remapeamento de \n é necessário e a substituição é invisível para o usuário, fazendo com que \n pareça ter o mesmo "significado" em ambos os contextos.)

    
por 21.04.2014 / 20:44
3

Você precisa se conectar à linha de comando; ao executá-lo via <CR> ou imediatamente quando você inserir um \n . Com :help c_CTRL-\_e , você pode avaliar uma função e modificar a linha de comando. Aqui está uma demonstração que você pode desenvolver e melhorar (a verificação de uma substituição é simplista agora):

cnoremap n <C-\>eTranslateBackslashN()<CR>
function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~# 's/.*/.*\$' " Improve this!
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
    
por 17.04.2014 / 20:58
1

Como Ingo Karkat escreveu, uma solução pode ser encontrada usando c_CTRL-\_e . Aqui está a versão que estou usando, que é idêntica à solução original, exceto pelo padrão regex. (Uma vez que esta é apenas a resposta de Ingo Karkat com uma melhora modesta sugerida por Ingo Karkat, eu não acho que ela realmente merece a sua própria resposta, mas eu acho que estou vencida: link )

function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~#
      \ '[%>]s\([um]\w*\)\?\(.\).\{-}\(\\)\@<!.*\$'
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
cnoremap n <C-\>eTranslateBackslashN()<CR>

Explicação do padrão de expressão regular:

  • [%>]s garante que a substituição ocorra somente quando s vier imediatamente após um intervalo
  • \([um]\w*\)\? corresponde às variações do comando s , como smagic .
  • \(.\) será o primeiro caractere não pertencente à palavra, já que todos os caracteres da palavra já serão comidos por \w no grupo opcional. Observe que este é o grupo 2 . Esse é o caractere separador, que geralmente é / . Observe que _ , que é um caractere de palavra, também é um separador válido, portanto, o padrão não funcionará corretamente se _ for usado dessa maneira. Eu nunca uso o _ como separador, então não vou me preocupar com isso. Da mesma forma, existem alguns caracteres que não são caracteres de palavras, mas que não devem ser usados como separadores, mas eu não estou preocupado com isso aqui, porque nesse caso o comando deve falhar de qualquer maneira. Eu queria usar \W aqui, mas por alguma razão isso não funcionou quando eu testei.
  • .\{-} deve corresponder ao padrão ( \{-} é como *? do Perl).
  • \(\\)\@<! corresponde à próxima instância do caractere separador não precedida por uma barra invertida. O equivalente em Perl seria (?<!\) .
  • .* corresponde ao que está na string de substituição até o momento.
  • \$ corresponde apenas se o comando até agora terminar com uma barra invertida.
por 18.04.2014 / 01:20