Wie suche ich in bestimmten Syntaxbereichen nach Mustern?


10

Ich benutze vim, um Latexdokumente zu bearbeiten. Oft möchte ich den Namen einer Variablen in etwas anderes ändern. Es ist jedoch etwas ärgerlich, wenn ich bei der Suche nach dem Variablennamen durch irrelevante Übereinstimmungen waten muss. Ich möchte nur in "Mathezonen" suchen, wie in der Tex-Syntaxdatei definiert. Gibt es eine einfache Möglichkeit, eine Suche auf einen bestimmten Syntaxbereich zu beschränken?


1
Ich denke, die Antwort lautet nein: Es gibt keine einfache Möglichkeit, eine Suche auf einen bestimmten Syntaxbereich zu beschränken.
Karl Yngve Lervåg

2
Diese Zuordnung wird verwendet synIDattr(), um Syntaxgruppen für das Zeichen unter dem Cursor zu erhalten. Sie können eine Funktion schreiben, die die Suche ausführt (oder ausführt normal n) und dann verwendet synIDattr(), um zu entscheiden, ob Sie an diesem Ort bleiben oder die Suche vorwärts fortsetzen möchten.
Joeytwiddle

@joeytwiddle Ich habe Ihren Kommentar gerade gesehen, nachdem ich eine Antwort mit einer solchen Funktion gepostet habe. Ist es so, wie du es dir vorgestellt hast?
Jjaderberg

@jjaderberg Ja das ist es. Gut gemacht!
Joeytwiddle

Nur der Vollständigkeit halber
VanLaser

Antworten:


4

Hier ist eine Funktion, die Sie ausprobieren können. Ich habe es nur ein wenig getestet, aber es scheint in Ordnung zu funktionieren.

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

Die Funktion ruft die Suchfunktion von Vim in einer Schleife auf, bis eine "normale" Übereinstimmung gefunden wird, die auch eine "qualifizierte" Übereinstimmung mit einem bestimmten Syntaxelement darstellt, oder bis das Ende des Puffers erreicht ist.

Es braucht zwei Argumente. Das erste ist das Suchmuster und wird unverändert an die search()Funktion von Vim weitergegeben . Sehen Sie, :help search()wie diese Funktion funktioniert. Das zweite Argument ist der Name des Syntaxelements, nach dem Sie diese Übereinstimmungen filtern möchten. Dies kann auch ein Muster sein und wird als regulärer Ausdruck ohne Berücksichtigung der Groß- und Kleinschreibung verglichen.

Um das Muster 'Alpha' in mathematischen Zonen zu finden, können Sie dies tun

:JJSyntaxSearch alpha texMathZone.

Das .am Ende ist das Musteratom für jedes einzelne Zeichen, siehe :help /.. Dies liegt daran, dass dort viele mathematische Zonensyntaxelemente usw. aufgerufen texMathZoneAwerden texMathZoneB.

Die search()Funktion bewegt den Cursor zur nächsten "normalen" Übereinstimmung. Dann erhält unsere Funktion alle Syntaxelement-IDs für diese neue Cursorposition mit synstack(). Beim Durchlaufen werden die Namen der einzelnen Elemente nacheinander abgerufen und anhand des syntaxitemArguments getestet . Siehe :help synstack()und :help synIDattr(). Wenn es eine 'qualifizierte' Übereinstimmung gibt, wird die Zeilennummer zurückgegeben. Wenn es das Ende des Puffers erreicht, ohne eine 'qualifizierte' Übereinstimmung zu finden, wird es zurückgegeben 0. Der Zweck der Funktion besteht darin, den Cursor auf die nächste 'qualifizierte' Übereinstimmung zu bringen, damit Sie dort eine Operation ausführen können. Es ist jedoch nützlich, "Zeilennummer oder 0" zurückzugeben, um anzugeben, ob es sinnvoll ist, die Funktion erneut aufzurufen, z Instanz, wenn Sie die Funktion wiederholt von einer anderen Funktion oder einem Makro aus aufrufen möchten.

Ich habe mich für das WFlag entschieden, search()weil es verhindert, dass das Ende des Puffers umwickelt wird. Andernfalls kann die Funktion hängen bleiben, da immer wieder dieselben "normalen" Übereinstimmungen gefunden werden, jedoch keine "qualifizierten" Übereinstimmungen.


Danke für Ihre Hilfe! Ich habe diese Funktion noch nicht ausprobiert, aber es sieht so aus, wie ich es wollte.
Rob F.


1

Wenn Ihre "mathematischen Zonen" durch ein syntaktisches Muster qualifiziert sind, z. B. die Zeichenfolge "math", können Sie zumindest Mustersequenzen verwenden , um eine Linie mit dem passenden Muster zu finden, wie in:

:/math//your pattern/

(Hinweis: Die beiden Muster können sich in unterschiedlichen Linien befinden!)

Dies beschränkt Ihre Übereinstimmungen möglicherweise nicht auf die Zonen - dafür müssten Sie das Ende der Zone identifizieren -, zeigt jedoch nur diese Übereinstimmungen nach einem anfänglichen Muster / math / an. Sie können die Suche nach dem nächsten Vorkommen mithilfe des Ex-Modus-Verlaufs ( : up-arrow enter) wiederholen .


Hinweis: ISTR, dass ich in früheren vim / vi-Versionen diese Methode auch direkt als Suchbefehl verwenden konnte (im Gegensatz zu einem Ex-Modus-Befehl), /math//your pattern/mit dem Vorteil, dass die Befehle nund weniger eingegeben und verwendet Nwerden müssen, aber ich kann sie nicht bestätigen das für meine aktuelle vim version.


1

Wenn Sie nach der Zeichenfolge fooin $...$oder suchen $$...$$, sollte dies funktionieren:

\$.*\zsfoo

Dies verankert die Übereinstimmung mit einem $Zeichen, wählt jedoch nur die Zeichenfolge aus foo.

Es ist keine einfache Lösung, aber man könnte ein :global+ verwenden :substitute, um "mathematische Zonen" zu finden und darin zu suchen:

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

Wenn :substituteSie so tun, als wäre dies ein Suchbefehl, können Sie mit zum nächsten Vorkommen mit gehen nund mit beenden q. Sollten Sie versehentlich eine Substitution bestätigen, sollte dies kein Problem darstellen.

Sie müssen die Liste in %(... )auf die Namen der von Ihnen verwendeten mathematischen Umgebungen einstellen (die vollständige Liste ist etwas umfangreich :) align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat. Beachten Sie, dass ich hier ein sehr magic ( \v) Muster verwende.

Erläuterung:

:globalausführen , um eine Ex - Befehl ( :s) in jeder Zeile , wo die Muster matches ( :help :global)
/\veine sehr magische Muster beginnen ( :h /, :h pattern, :h magic)
\\begin\{eine wörtliche entsprechen \begin{
%(align|alignat|displaymath)einem dieser Wörter Match ( :h /\%(, :h /bar)
\}/eine wörtliche übereinstimmen }und das Muster beenden.

+1,/\\end/-1Ein Bereich, der aus der nächsten Zeile (von der gefundenen bis :global) bis zur Zeile vor der vom Suchmuster gefundenen Zeile besteht /\\end. Innerhalb dieses Bereichs

s/foo/&/gcSuchen und Ersetzen jedes Vorkommens des Literals foodurch sich selbst nach Bestätigung ( :h :substitute)


Dies ist sicherlich ein Anfang, aber ich verwende häufig die Gleichungs-, Ausrichtungs- und IEEEeqnarray-Umgebungen und möchte diese nicht von meiner Suche ausschließen.
Rob F.

@RobF.: Es ist durchaus möglich, in einer Reihe von Umgebungen Übereinstimmungen herzustellen, aber es wird nicht einfach, wenn man es nicht per Skript schreibt. Wenn Sie jedoch regelmäßig \mathitVariablennamen verwenden, ist es viel einfacher, sie zu finden.
Peter Lewerin

0

Wenn Sie suchen nach der Zeichenfolge ‚Morgen‘ innen Datei /morningdann enterund drücken nVorwärtsrichtung bewegen


1
Die Frage besagt, dass I would like to search only in "math zones"Ihre Methode nach der gesamten Datei sucht und keine Forschungszone begrenzt.
Statox

0

Es bleibt keine andere Wahl, als eine dedizierte Funktion dafür zu schreiben. Ich habe eine Funktion geschrieben, die die gewünschte Zeichenfolge durchsucht und nur dann stoppt, wenn:

  1. Es gehen die Streichhölzer aus
  2. Es gibt eine Übereinstimmung, die sich in der mathematischen Umgebung befindet (sie stoppt bei der Übereinstimmung).

Sie rufen es einfach mit der Zeichenfolge auf, die Sie suchen möchten.

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

Ich beabsichtige, eine ähnliche Funktion für GrammerousCheck zu schreiben, die nur bei Grammatikfehlern außerhalb der Mathematik stoppt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.