Como procurar padrões em determinadas regiões de sintaxe?


10

Estou usando o vim para editar documentos de látex. Muitas vezes, vou querer mudar o nome de uma variável para outra coisa. No entanto, é um pouco chato ter que percorrer correspondências irrelevantes quando procuro o nome da variável. Eu gostaria de pesquisar apenas em "zonas matemáticas", conforme definido no arquivo de sintaxe tex. Existe uma maneira fácil de limitar uma pesquisa a uma região de sintaxe específica?


11
Acho que a resposta é não: não há uma maneira fácil de limitar uma pesquisa a uma região de sintaxe específica.
Karl Yngve Lervåg

2
Esse mapeamento usa synIDattr()para obter grupos de sintaxe para o caractere sob o cursor. Você pode escrever uma função que realiza a pesquisa (ou faz normal n) e depois usa synIDattr()para decidir se deve permanecer nesse local ou continuar a pesquisa adiante.
Joeytwiddle

@joeytwiddle Vi seu comentário agora mesmo depois de postar uma resposta com essa função. É como o que você tinha em mente?
Jjaderberg 11/08

@jjaderberg Sim, é. Bom trabalho!
Joeytwiddle

Apenas para a completude (eu achei uma boa resposta): stackoverflow.com/a/2696143/5000478
VanLaser

Respostas:


4

Aqui está uma função que você pode tentar. Eu só testei um pouco, mas parece funcionar bem.

function! JJSyntaxSearch(pattern, syntaxitem)
  while search(a:pattern, 'W') > 0
    for id in synstack(line("."),col("."))
      if synIDattr(id,"name") =~? a:syntaxitem
        return line(".")
      endif
    endfor
  endwhile
  return 0
endfunc

command! -nargs=* JJSyntaxSearch call JJSyntaxSearch(<f-args>)

A função chama a função de pesquisa do Vim em um loop até encontrar uma correspondência 'comum' que também é uma correspondência 'qualificada' para um item de sintaxe específico ou até chegar ao final do buffer.

São necessários dois argumentos. O primeiro é o padrão de pesquisa e é passado inalterado para a search()função do Vim . Veja :help search()como essa função funciona. O segundo argumento é o nome do item de sintaxe no qual você deseja filtrar essas correspondências. Isso também pode ser um padrão e é comparado como uma expressão regular que não diferencia maiúsculas de minúsculas.

Para encontrar o padrão 'alfa' nas zonas matemáticas, você pode fazer

:JJSyntaxSearch alpha texMathZone.

O .no final é o átomo padrão para qualquer caractere único, veja :help /.. Isso ocorre porque há muitos itens de sintaxe zona matemática chamada texMathZoneA, texMathZoneBetc.

A search()função move o cursor para a próxima correspondência 'comum'. Em seguida, nossa função obtém todos os IDs de item de sintaxe para essa nova posição do cursor synstack(). Dando um loop neles, ele recupera o nome de cada item e o testa contra o syntaxitemargumento. Veja :help synstack()e :help synIDattr(). Se houver uma correspondência 'qualificada', ele retornará o número da linha. Se atingir o final do buffer sem encontrar nenhuma correspondência 'qualificada', ele retornará 0. O objetivo da função é levar o cursor para a próxima correspondência 'qualificada', para que você possa fazer alguma operação lá, mas é útil retornar "número da linha ou 0" para indicar se é significativo chamar a função novamente, por exemplo, se você quiser chamar a função repetidamente de outra função ou macro.

Eu escolhi usar o Wsinalizador para search()isso porque ele evita 'envolver' o final do buffer. Caso contrário, a função poderá ficar paralisada, pois continua encontrando as mesmas correspondências "comuns", mas nenhuma correspondência "qualificada".


Obrigado pela ajuda! Ainda não tentei essa função, mas parece que eu queria.
Rob F.


1

Caso suas "zonas matemáticas" sejam qualificadas por algum padrão sintático, por exemplo, a string "math", você pode pelo menos usar sequências de padrões para encontrar uma linha com o padrão correspondente, como em:

:/math//your pattern/

(Nota: os dois padrões podem estar em linhas diferentes!)

Isso pode não restringir suas correspondências às zonas - para isso você precisa identificar o final da zona -, mas exibirá apenas essas correspondências após um padrão inicial / math /. Você pode repetir a pesquisa para a próxima ocorrência usando o histórico do modo ex ( : up-arrow enter).


Nota: ISTR que nas versões anteriores do vim / vi eu também era capaz de usar esse método diretamente como um comando de pesquisa (em oposição a um comando ex-mode) /math//your pattern/com a vantagem de menos digitação e uso dos comandos ne N, mas não posso confirmar isso para a minha versão atual do vim.


1

Se você estiver procurando pela string foodentro $...$ou $$...$$, isso deve funcionar:

\$.*\zsfoo

Isso ancora a correspondência em um $caractere, mas seleciona apenas a sequência foo.

Não é realmente uma solução fácil, mas é possível usar um :global+ :substitutepara encontrar "zonas matemáticas" e pesquisar dentro delas:

:global /\v\\begin\{%(align|alignat|displaymath)\}/ +1,/\\end/-1 s/foo/&/gc

Fingindo que :substituteé um comando de pesquisa, você pode ir para a próxima ocorrência com ne sair com q. Se você confirmar uma substituição por engano, não deverá haver nenhum problema.

Você terá que definir a lista dentro de %(... )com os nomes dos ambientes matemáticos que você usa (a lista completa é um pouco pesada:) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Observe que estou usando um \vpadrão muito mágico ( ) aqui.

Explicação:

:globalexecutar um comando Ex ( :s) em cada linha onde os jogos padrão ( :help :global)
/\viniciar um padrão muito mágico ( :h /, :h pattern, :h magic)
\\begin\{corresponder a um literal \begin{
%(align|alignat|displaymath)jogo qualquer uma destas palavras ( :h /\%(, :h /bar)
\}/corresponder a um literal }e acabar com o padrão.

+1,/\\end/-1um intervalo que consiste na próxima linha (contando desde a encontrada por :global) até a linha anterior à encontrada pelo padrão de pesquisa /\\end. Dentro desse intervalo,

s/foo/&/gcpesquise e substitua todas as ocorrências do literal foopor si mesmo, após confirmação ( :h :substitute)


Isso certamente é um começo, mas uso frequentemente os ambientes de equação, alinhamento e IEEEeqnarray, e não quero excluir os da minha pesquisa.
Rob F.

@RobF .: é bem possível combinar dentro de uma variedade de ambientes, mas não será fácil, a menos que se faça um script. Se, no entanto, você sempre usa \mathitnomes de variáveis, é muito mais fácil encontrá-los.
Peter Lewerin

0

Se você estiver procurando a string 'manhã' dentro do arquivo /morning, em seguida, entere pressione npara mover direção para frente


11
A pergunta dizia que I would like to search only in "math zones"seu método procura o arquivo inteiro e não delimita uma zona de pesquisa.
statox

0

Não há opção a não ser escrever uma função dedicada para isso. Eu escrevi uma função que pesquisa a string que você deseja e só para se:

  1. fica sem correspondências
  2. há uma correspondência dentro do ambiente matemático (ela será interrompida)

Você acabou de chamá-lo com a string que deseja pesquisar.

function! Finmath(nextstr)
    while 1
        if search(a:nextstr)==0
            break
        endif
        if searchpairpos('\(', '','\)','n')!=[0,0]
            break
        endif
        if searchpairpos('\[', '','\]','n')!=[0,0]
            break
        endif
        let a = getcurpos() 
        if count(strpart(getline('.'),0,a[2]),'$')%2==1
            break
        endif 
    endwhile 
endfunction

Pretendo escrever uma função semelhante para o GrammerousCheck que só para com erros gramaticais fora da matemática.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.