Realçar automaticamente texto de linhas idênticas

13

Eu vi um ninja vim habilidoso fazer isso há algum tempo, mas não tenho idéia para começar.

A) Existe uma maneira de configurar a cor de fundo dos vims para que linhas consecutivas com conteúdo idêntico sejam destacadas.

B) Se alguém souber como fazer isso, um bom ajuste seria se o realce acontecesse em linhas consecutivas, mas considere apenas a primeira palavra (não a linha inteira).

Um segundo ajuste, se o realce puder ser configurado para cores diferentes, será usado com base no número de linhas correspondentes (ou as palavras dependendo de AB estiverem ativas). Portanto, temos apenas duas linhas consecutivas que correspondem a verde, 3-5 linhas consecutivas e laranja, 6+ e vermelho.

Martin York
fonte
Artigo

Respostas:

10

Os seguintes matchconjuntos parecem funcionar para (A):

:syn match Low /\v(.+)\n(\1\n)/
:syn match Medium /\v(.+)\n(\1\n){2,4}/
:syn match Critical /\v(.+)\n(\1\n){5,}/
:hi Critical  ctermfg=red
:hi Medium  ctermfg=yellow
:hi Low  ctermfg=green

Parece que a ordem é crucial aqui. Se as correspondências Lowou Mediumvierem depois Critical, elas serão incluídas nos requisitos mais frouxos delas e da mesma forma para Lowwrt Medium.

O realce não aparece imediatamente após você adicionar, digamos, uma terceira ou sexta linhas duplas, mas depois que você se move um pouco depois de adicioná-las. Não tenho certeza do que exatamente o desencadeia.

Para B, imagino que você possa substituir o regex por:

/\v(\S+).*\n(\1.*\n)/

Em geral, substitua (.*)por (\S+).*e \1com \1.*, ou o que constitui uma palavra para você.

muru
fonte
Dei a resposta a essa pergunta porque, para mim, é como fazer o destaque que eu precisava (como expresso pela pergunta). A expressão regular @Matts é boa, mas não responde à pergunta real que eu fiz (alterando o destaque).
Martin York
8

Como ponto de partida, eis um padrão de pesquisa que corresponde a linhas duplicadas (ignorando alterações no espaço em branco à esquerda):

              \zs                marks start of the pattern. Everything before here will not be highlighted
 ^                               start of the line
  \s*                            leading whitespace
       .\+                       match 1 or more non-newline characters
     \(   \)                     and use parens to capture this in match group 1

            \n                   match the newline character
                 \(        \)\+  1 or more
                      \1         copies of what was in the match group 1
                   \s*  \n       with leading whitespace followed by a newline
/^\s*\(.\+\)\n\zs\(\s*\1\n\)\+   the full regex

:help pattern fornecerá mais informações sobre como fazer regexes como este

:help syntax mostrará como pegar essa expressão regular e transformá-la em algo destacado para você

Aprender a escrever scripts de sintaxe pode ser difícil, portanto, uma boa solução a curto prazo é fazer isso 'on the fly', certificando- 'incsearch'se de que seja definido para que as pesquisas sejam destacadas e mapeando uma chave para fazer a pesquisa acima, ou seja,nnoremap <F5> /^\s*\(.\+\)\n\zs\(\s*\1\n\)\+<CR>

Matt Boehm
fonte
Existe alguma maneira automatizada de distribuir a regex dessa maneira? Ele fornece uma representação tão clara.
muru
1
Eu tenho feito isso manualmente. A maneira mais fácil e rápida no vim seria fazer algo como yy10pna linha com o regex completo e selecionar as partes que você deseja remover e pressionar r<space>. Talvez eu adicione um comando para 'substituir tudo, exceto a seleção nesta linha por espaços', para acelerar um pouco as coisas.
Matt Boehm
Uau! Isso é bastante esforço!
muru
1
Eu criei uma função vim (realmente feia) para tornar isso um pouco mais rápido: gist.github.com/mattboehm/da63a48eedf6f14375aa . Selecione uma linha, pressione ,re junte as linhas <space>no modo normal / visual.
Matt Boehm