Wie finde ich umgebende Klammern (von emacs lisp)?

7

Gibt es eine Möglichkeit, den Typ der umgebenden Klammer (dh '(', '[' oder '{') um den Punkt herum herauszufinden? Zum Beispiel (Verwenden |, um einen Punkt darzustellen)

{ abc, | df }

sollte '{' zurückgeben, und

{ abc[ | ], 123 }

sollte '[' zurückgeben. Idealerweise möchte ich, dass es auch Anführungszeichen behandelt.


Für den Fall, dass jemand neugierig ist oder weitere Details benötigt: Mein Ziel ist es, :mithilfe von elektrischen Abständen (auch als Smart-Operator bezeichnet ) einen intelligenten automatischen Abstand in Python einzurichten . Das Problem ist, dass normalerweise (in Python) :entweder der Slice-Operator oder der Beginn einer for / if / ... -Anweisung ist, die nicht von Leerzeichen umgeben sein sollte. Innerhalb eines Wörterbuchs ist es jedoch so etwas wie ein Zuweisungsoperator und sollte daher von Leerzeichen umgeben sein. Ich muss also überprüfen, ob sich der Punkt innerhalb eines Diktats befindet (dh innerhalb {}), aber nicht innerhalb einer Slice-Operation oder einer Zeichenfolge innerhalb dieses Dikts (dh nicht innerhalb []oder "").


Bearbeiten:

Hier ist die Hilfsfunktion, die ich basierend auf der Antwort von abo-abo geschrieben habe:

(defun enclosing-paren ()
  "Return the closing parenthesis of the enclosing parens, or nil if not inside any parens."
  (ignore-errors
    (save-excursion
      (up-list)
      (char-before))))

Dann ist das letzte Prädikat:

(and (not (in-string-p))
     (eq (enclosing-paren) ?\}))

Bearbeiten 2:

Die obige Funktion erwies sich als zu langsam (sie verursachte häufig eine merkliche Verzögerung, wenn a :eingegeben wurde). Ich verwende jetzt stattdessen Stefans Antwort, die viel schneller zu sein scheint.

dshepherd
quelle
1
Keine vollständige Antwort, aber für den speziellen Fall von ""können Sie die integrierte Funktion verwenden in-string-p.
T. Verron

Antworten:

10

Anstatt dass up-listich empfehlen würde, dass Sie verwenden, (syntax-ppss)was Ihnen einen Parsing-Status zurückgibt. Dies beinhaltet Informationen darüber, ob Sie sich in einer Zeichenfolge oder einem Kommentar befinden, die Position des letzten geöffneten "Parens" usw.

ZB können Sie die Art von Paren mit finden

(let ((ppss (syntax-ppss)))
  (when (nth 1 ppss) (char-after (nth 1 ppss))))

und hoffentlich sollten Sie auch mit Anführungszeichen umgehen können (durch Aktivieren von (nth 3 ppss)und (char-after (nth 8 ppss))).

Stefan
quelle
5

Versuche dies:

(save-excursion
  (up-list)
  (char-before))

Beachten Sie, dass up-listwerfen kann, so dass Sie auch Fehler behandeln müssen.

abo-abo
quelle
1
Ich mag die Einfachheit dieser Antwort, aber es stellte sich heraus, dass sie in Python zu langsam ist, wenn der Punkt nicht in einem Parens liegt (sehr häufig bei der Whitespace-Syntax von Python). Vermutlich liegt es daran, dass in diesem Fall der gesamte Puffer analysiert wird.
Dshepherd
1

Während die bevorzugte Antwort IMO von Stefan gegeben wurde, hier ein Beispiel, das eine Lösung enthält, die sich nicht auf WRT-Trennzeichen für Syntaxtabellen stützt: Es verwendet so etwas wie

 (skip-chars-backward "^{\(\[\]\)}")

und ein Stapel. Siehe Quelle hier

https://github.com/emacs-berlin/general-close

Andreas Röhler
quelle
0

Hier ist eine Funktion, die die umgebende Klammer zurückgibt, einschließlich des Falls, wenn der Punkt direkt auf der ersten oder letzten Klammer liegt (was in meinem Fall wichtig war).

Dies funktioniert mit der Sprache, sodass ({[]})alle beispielsweise in C funktionieren.

(defun find-surrounding-brackets (pos)
  "Return a pair of buffer positions for the opening & closing bracket positions.

Or nil when nothing is found."
  (save-excursion
    (goto-char pos)
    (when
      (or
        ;; Check if we're on the opening brace.
        (when
          ;; Note that the following check for opening brace
          ;; can be skipped, however it can cause the entire buffer
          ;; to be scanned for an opening brace causing noticeable lag.
          (and
            ;; Opening brace.
            (eq (syntax-class (syntax-after pos)) 4)
            ;; Not escaped.
            (= (logand (skip-syntax-backward "/\\") 1) 0))
          (forward-char 1)
          (if (and (ignore-errors (backward-up-list arg) t) (eq (point) pos))
            t
            ;; Restore location and fall through to the next check.
            (goto-char pos)
            nil))
        ;; Check if we're on the closing or final brace.
        (ignore-errors (backward-up-list arg) t))
      ;; Upon success, return the pair as a list.
      (list
        (point)
        (progn
          (forward-list)
          (1- (point)))))))
ideasman42
quelle