Come cercare pattern in determinate regioni della sintassi?


10

Sto usando VIM per modificare i documenti in lattice. Spesso, vorrò cambiare il nome di una variabile in qualcos'altro. Tuttavia, è un po 'fastidioso dover superare partite irrilevanti quando cerco il nome della variabile. Vorrei cercare solo in "zone matematiche" come definito nel file di sintassi tex. Esiste un modo semplice per limitare una ricerca a una regione di sintassi specifica?


1
Penso che la risposta sia no: non esiste un modo semplice per limitare una ricerca a una specifica regione di sintassi.
Karl Yngve Lervåg,

2
Questa mappatura utilizza synIDattr()per ottenere gruppi di sintassi per il carattere sotto il cursore. È possibile scrivere una funzione che esegue (o fa normal n) la ricerca e quindi utilizza synIDattr()per decidere se rimanere in questa posizione o continuare la ricerca in avanti.
joeytwiddle,

@joeytwiddle Ho visto il tuo commento proprio ora dopo aver pubblicato una risposta con tale funzione. È come quello che avevi in ​​mente?
Jjaderberg,

@jjaderberg Sì, lo è. Ottimo lavoro!
joeytwiddle,

Solo per completezza (ho trovato una buona risposta): stackoverflow.com/a/2696143/5000478
VanLaser

Risposte:


4

Ecco una funzione che potresti provare. L'ho provato solo un po ', ma sembra funzionare bene.

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>)

La funzione chiama la funzione di ricerca di Vim in un ciclo fino a quando non trova una corrispondenza "normale" che è anche una corrispondenza "qualificata" con un particolare elemento di sintassi o fino a quando non raggiunge la fine del buffer.

Ci vogliono due argomenti. Il primo è il modello di ricerca e viene passato invariato alla search()funzione di Vim . Scopri :help search()come funziona quella funzione. Il secondo argomento è il nome dell'elemento di sintassi su cui si desidera filtrare queste corrispondenze. Questo può anche essere un modello ed è confrontato come un'espressione regolare senza distinzione tra maiuscole e minuscole.

Per trovare lo schema 'alfa' nelle zone matematiche che puoi fare

:JJSyntaxSearch alpha texMathZone.

Alla .fine è l'atomo modello per ogni singolo personaggio, vedi :help /.. Questo perché ci sono molti elementi di sintassi della zona matematica chiamati texMathZoneA, texMathZoneBecc.

La search()funzione sposta il cursore sulla corrispondenza 'ordinaria' successiva. Quindi la nostra funzione ottiene tutti gli ID degli elementi di sintassi per quella nuova posizione del cursore con synstack(). Effettuando un ciclo tra loro, recupera a turno il nome di ciascun elemento e lo verifica con l' syntaxitemargomento. Vedi :help synstack()e :help synIDattr(). Se esiste una corrispondenza "qualificata", viene restituito il numero di riga. Se raggiunge la fine del buffer senza trovare alcuna corrispondenza "qualificata", viene restituito 0. Il punto della funzione è di portare il cursore sulla corrispondenza 'qualificata' successiva in modo da poter eseguire qualche operazione lì, ma è utile restituire "numero di riga o 0" per indicare se è significativo chiamare nuovamente la funzione, per istanza se si desidera chiamare ripetutamente la funzione da un'altra funzione o una macro.

Ho scelto di usare il Wflag per il search()perché impedisce di "avvolgere" la fine del buffer. Altrimenti la funzione potrebbe rimanere bloccata poiché continua a trovare le stesse corrispondenze "normali" ma nessuna corrispondenza "qualificata".


Grazie per l'aiuto! Non ho ancora provato questa funzione, ma sembra quello che volevo.
Rob F.


1

Nel caso in cui le tue "zone matematiche" siano qualificate da un modello sintattico, diciamo la stringa "matematica", allora potresti almeno usare le sequenze di modelli per trovare una linea con il modello corrispondente, come in:

:/math//your pattern/

(Nota: i due motivi possono essere su linee diverse!)

Questo potrebbe non limitare le tue partite alle zone - per questo dovresti identificare la fine della zona -, ma mostrerà solo quelle partite dopo un modello iniziale / matematica /. È possibile ripetere la ricerca dell'occorrenza successiva utilizzando la cronologia ex-mode ( : up-arrow enter).


Nota: ISTR che nelle precedenti versioni di vim / vi ero anche in grado di usare quel metodo direttamente come comando di ricerca (al contrario di un comando ex-mode) /math//your pattern/con il vantaggio di digitare e usare meno i comandi ne N, ma non posso confermare quello per la mia attuale versione di vim.


1

Se stai cercando la stringa fooall'interno $...$o $$...$$, dovrebbe funzionare:

\$.*\zsfoo

Questo fissa la corrispondenza a un $personaggio ma seleziona solo la stringa foo.

Non è davvero una soluzione facile, ma si potrebbe usare un :global+ :substituteper trovare "zone matematiche" e cercare al loro interno:

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

Fingendo che :substitutesia un comando di ricerca, puoi andare alla ricorrenza successiva con ned uscire con q. Se dovessi confermare una sostituzione per errore, non ci dovrebbero essere problemi.

Dovrai impostare l'elenco all'interno %(... )sui nomi degli ambienti matematici che usi (l'elenco completo è un po 'pesante:) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Nota che sto usando un modello molto magico ( \v) qui.

Spiegazione:

:globaleseguire un comando Ex ( :s) su ciascuna riga in cui le partite di pattern ( :help :global)
/\viniziano un modello molto magico ( :h /, :h pattern, :h magic)
\\begin\{corrispondere una costante \begin{
%(align|alignat|displaymath)corrispondenza qualsiasi di queste parole ( :h /\%(, :h /bar)
\}/corrispondere una costante }e terminare il modello.

+1,/\\end/-1un intervallo costituito dalla riga successiva (contando da quella trovata da :global) fino alla riga precedente a quella trovata dal modello di ricerca /\\end. All'interno di tale intervallo,

s/foo/&/gccerca e sostituisci ogni ricorrenza del letterale foocon se stesso, dopo la conferma ( :h :substitute)


Questo è certamente un inizio, ma uso spesso gli ambienti di equazione, allineamento e IEEEeqnarray e non voglio escluderli dalla mia ricerca.
Rob F.

@RobF .: è possibile abbinarlo all'interno di una vasta gamma di ambienti, ma non sarà facile se non lo si scrive. Se, tuttavia, usi costantemente i \mathitnomi delle variabili, trovarli è molto più semplice.
Peter Lewerin,

0

Se stai cercando la stringa 'morning' all'interno del file, /morningquindi enterpremi nper andare avanti


1
La domanda dice che il I would like to search only in "math zones"tuo metodo cerca l'intero file che non delimita una zona di ricerca.
statox

0

Non c'è altra scelta che scrivere una funzione dedicata per questo. Ho scritto una funzione che cerca la stringa desiderata e si ferma solo se:

  1. finisce le partite
  2. c'è una partita che si trova all'interno dell'ambiente matematico (si fermerà sulla partita)

Lo chiami semplicemente con la stringa che vuoi cercare.

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

Intendo scrivere una funzione simile per GrammerousCheck che si ferma solo su errori grammaticali al di fuori della matematica.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.