So bearbeiten Sie elisp, ohne sich in Klammern zu verlieren


13

Ich ändere einen Elisp-Code aus linum.el:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Ich war in der Lage einen Fehler zu beheben , wo die Vertiefung war off-by-one durch Modifizierung (count-lines (point-min) (point-max))zu (+ (count-lines (point-min) (point-max)) 1). Das war einfach.

Aber jetzt möchte ich es so ändern, dass die minimale Breite 2 ist, indem ich eine if-Bedingung hinzufüge, (concat " %" (number-to-string w) "2d ")wenn die Zeilenzahl <10 ist.

Das sollte einfach sein! Fügen Sie eine Bedingung hinzu und kopieren Sie das Concat. Stück Kuchen, richtig? Ich weiß, was ich tun soll , aber ich berühre elisp selten und bin immer entmutigt, wenn ich irgendetwas in Klammern ändern muss.

Nach meinem Verständnis besteht der "richtige" Stil darin, den Code auf der Grundlage von Einrückungen zu strukturieren und die abschließenden Klammern am Ende einer Zeile und nicht allein zu setzen. Da ich aus anderen C-Sprachen komme, habe ich Probleme, Code auf diese Weise zu lesen und zu schreiben. Meine Frage lautet also: Was mache ich falsch? Wie soll ich elisp editieren und im Code navigieren, damit ich nicht alle Klammern aufzählen muss?

Wenn ich mit etwas arbeite, das zu tief wird, muss ich meine Tür schließen, die Jalousien ziehen und die Klammer K & R so positionieren, dass ich das verdammte Ding nicht nur lesen, sondern auch modifizieren kann, ohne auszuflippen.

Offensichtlich mache ich das alles falsch. Wie kann ich elisp so ohne Angst berühren?

Bitte beachte, dass meine Frage, wie man durch elisp navigiert und es bearbeitet, keine Frage zum Stil ist. Als Styleguide verwende ich bereits: https://github.com/bbatsov/emacs-lisp-style-guide

Aktualisierung:

So formatieren Sie elisp richtig, bevor Sie sich auf emacs.stackexchange in Verlegenheit bringen:

Markieren Sie Ihr Elisp und führen Sie durch M-x indent-region.

Die Problemlösung:

Für diejenigen, die wissen möchten, wie man eine Rechtfertigung für Linum mit einer Mindestbreite von zwei ausführt, ist hier die Lösung:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1)
                           (concat " %" (number-to-string w) "d ")
                         " %2d ")))
    ad-do-it))

1
Jeder hat Probleme mit dem Lispeln, das von C kommt. Es braucht nur Zeit, aber irgendwann wird es extrem natürlich. Sie können Ihr Problem wahrscheinlich auch lösen, indem Sie das linum-Format in eine Formatzeichenfolge wie "% 2d" ändern.
Jordon Biondo

Ich kann nicht einfach verwenden, %2dda die Breite von rechtsbündig nach linksbündig wechselt, sobald sie sich auf 3 oder mehr Zeichen bewegt.
Zhro,

Es gibt einige Bibliotheken, die übereinstimmende Klammern hervorheben, die (meiner Meinung nach) von unschätzbarem Wert sind, z highlight-parentheses. rainbow-delimiters; usw. Hier ist meine eigene vereinfachte Version highlight-parentheses, die das Scrollen ermöglicht, ohne die Klammern zu entfernen, die zuletzt eingefärbt wurden: stackoverflow.com/a/23998965/2112489 In Zukunft ist es eine Frage pro Kunde / Thread.
Gesetzesliste

1
Es hört sich so an, als würde Ihr Problem wirklich lesen und nicht den Elisp-Code bearbeiten. Sie hören sich an, als hätten Sie Probleme, die Struktur von Lisp zu verstehen, und das beeinträchtigt Ihre Bearbeitung.
PythonNut

1
Zu Ihrer Verteidigung ist das ein ziemlich stark eingerückter Code. Ich habe es selbst die ersten 3 Male falsch gelesen. Auch paredit .
Malabarba

Antworten:


12

Es gibt eine Reihe von Add-On-Paketen, die möglicherweise hilfreich sind, z. B. paredit, smartparens und lispy. Diese Pakete erleichtern das Navigieren und Manipulieren von Lisp-Code, sodass Sie in S-Ausdrücken denken und sich der Editor um das Ausgleichen von Parens kümmern kann.

Emacs verfügt auch über zahlreiche integrierte Befehle für den Umgang mit lernenswerten Sexps und Listen, mit denen Sie sich möglicherweise besser an die Struktur von Lisp-Code gewöhnen können. Diese sind in der Regel mit einem C-M-Präfix verbunden, z.

  • C-M-f/ C-M-bvorwärts / rückwärts bewegen durch sexp
  • C-M-n/ C-M-pvorwärts / rückwärts durch Liste bewegen
  • C-M-u/ C-M-dum eine Ebene hoch / runter zu gehen
  • C-M-t die zwei Sexps um Punkt zu tauschen
  • C-M-k ein sexp töten
  • C-M-SPC ein sexp markieren
  • C-M-q ein Geschlecht neu einrücken

Der Beispielcode, den Sie angegeben haben, ist möglicherweise klarer, wenn Sie den Einzug korrigieren: Setzen Sie den Punkt an den Anfang von (defadvice...und C-M-qdrücken Sie, um den gesamten Ausdruck erneut einzurücken. Um das zu ersetzen, (concat...würde ich anfangen, indem ich den Punkt an den Anfang dieses Geschlechts setze und C-M-odie Linie spalte, während die Einrückung erhalten bleibt . Fügen Sie dann Ihre hinzu (if..., und verwenden Sie die obigen Befehle, um zum Ende einer Liste zu springen, um eine weitere schließende Parene hinzuzufügen, zum Anfang zurückzukehren, um die Parene erneut einzurücken usw.

Möglicherweise möchten Sie auch einschalten show-paren-mode, wodurch der entsprechende Paren hervorgehoben wird, wenn sich der Punkt am Anfang oder Ende einer Liste befindet. Möglicherweise möchten Sie lieber den gesamten Ausdruck hervorheben als den passenden Ausdruck. Passen Sie ihn also an show-paren-style.

Wie @Tyler in den Kommentaren zu einer anderen Antwort erwähnt hat, sollten Sie sich das Handbuch ansehen , um mehr über diese und verwandte Befehle zu erfahren.


Beachten Sie, dass der Ausdruck C-M-qmit einem Präfixargument ( C-u C-M-q) aufgerufen werden kann, um ihn an der Stelle hübsch auszudrucken. Dadurch wird alles in separate Zeilen aufgeteilt und eingerückt, sodass die Verschachtelung sehr offensichtlich ist. Sie möchten im Allgemeinen nicht, dass Ihr Lisp-Code so aussieht, aber es kann hilfreich sein, ein bisschen Code zu verstehen, ohne manuell auf K & R zuzugreifen. (Und Sie können immer C-x urückgängig machen).
Glucas

6

Eine gute Möglichkeit, LISP zu bearbeiten, besteht darin, den AST anstelle der einzelnen Zeichen oder Zeilen zu manipulieren. Ich habe das mit meinem Paket lispy gemacht , das ich vor 2 Jahren gestartet habe. Ich denke, es kann einiges an Übung erfordern, um zu lernen, wie man das gut macht, aber selbst wenn man nur die Grundlagen verwendet, sollte das schon hilfreich sein.

Ich kann erklären, wie ich diese Änderung vornehmen würde:

Schritt 1

Die Ausgangsposition ist normalerweise, den Punkt vor dem Top-Level-Sex zu haben. Hier |ist der Punkt.

|(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Sie möchten, dass der Code richtig eingerückt ist, drücken Sie also ieinmal. Es wird es schön wieder einrücken.

Schritt 2

Sie möchten "d "mit einer Region markieren , da ein manipulierbares Objekt in lispyentweder eine Liste ist, die nicht markiert werden muss, oder eine Folge von Symbolen oder / und Listen, die mit einer Region markiert werden müssen.

Drücken Sie atdazu. Der aBefehl ermöglicht das Markieren eines einzelnen Symbols in der übergeordneten Liste und tist der Index dieses bestimmten Symbols.

Schritt 3

  1. Um die aktuelle Region mit zu umbrechen (), drücken Sie (.
  2. Drücken Sie C-f, um ein Zeichen vorwärts zu bewegen und einzufügen if.
  3. Drücken Sie (erneut einzufügen ().
  4. Einfügen > w 10.
  5. C-f C-m um die Zeichenfolge in eine neue Zeile zu verschieben.

Schritt 4

So klonen Sie den String:

  1. Markieren Sie das Symbol oder die Zeichenfolge am Punkt mit M-m.
  2. Drücken Sie c.

Wenn Sie die Region auf ausgefallene Weise deaktivieren und den Punkt ganz am Anfang der Zeichenfolge platzieren möchten, können Sie Folgendes drücken idm:

  1. i wählt den inneren Inhalt der Zeichenkette aus.
  2. d Punkt tauschen und markieren.
  3. m deaktiviert die Region

Oder Sie könnten m C-b C-b C-bin diesem Fall tun , oder C-g C-b C-b C-b. Ich denke, es idmist besser, da es unabhängig von der Länge der Saite gleich ist. Ich denke das C-x C-x C-f C-g würde auch unabhängig von der Stringlänge funktionieren.

Zuletzt einfügen 2, um den Endcode zu erhalten:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) (if (> w 10)
                                                             "2|d "
                                                           "d "))))
    ad-do-it))

Zusammenfassung

Die vollständige Sequenz war: at( C-f, if, (, > w 10, C-f C-m M-m cidm, 2.

Beachten Sie, dass, wenn Sie die Codeeinfügung auszählen, die einzigen Schlüssel, die sich nicht auf die AST-Manipulation beziehen, zwei C-fund eins waren C-m.


3
Lispy klingt interessant! Zum OP: Sie können ähnliche Workflows mit paredit: emacsrocks.com/e14.html entwickeln und region: github.com/magnars/expand-region.el erweitern oder einfach nur mit den eingebauten Befehlen für den Klammervergleich herumspielen: gnu . org / software / emacs / manual / html_node / emacs / Parentheses.html
Tyler

Ich bin sicher, Sie haben geraten, als Sie das Problem für mich lösen wollten. Danke für den Versuch. Ich habe es geschafft, mich anhand Ihres Codes durchzuschlagen. Die richtige Lösung finden Sie in meinem Update.
Zhro

6

Sie werden sich mit der Zeit daran gewöhnen, aber natürlich können Sie vieles tun, um es zu beschleunigen:

Vertiefung

Es gibt eine Methode für diesen Wahnsinn. In Lisp können Sie dies tun:

(a-fun (another-fun (magic-macro 1)))

Angenommen, das 1ist wirklich ein großer Ausdruck, und Sie möchten ihn in einer eigenen Zeile einrücken.

(a-fun (another-fun (magic-macro 
  1)))

Das ist irreführend. 1wird nur ein Slot eingerückt, obwohl es sich um ganze drei Verschachtelungsebenen höher handelt! Besser von seinen Eltern.

(a-fun (another-fun (magic-macro 
                      1)))

Wenn wir dieses Schema für Ihren eigenen Code verwenden, erhalten wir Folgendes:

(custom-set-variables '(linum-format 'dynamic))
(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                      (+ (count-lines (point-min) (point-max)) 1))))       
          (linum-format 
            (concat " %" (number-to-string w) "d ")))
     ad-do-it))

Beachten Sie die starke Korrelation zwischen Einrückung und Verschachtelungsebene. Zeilen mit einem höheren Verschachtelungsgrad werden immer mehr eingerückt als Zeilen mit weniger.

Dies allein wird viel helfen. Sie können die "Form" des Codes leicht erkennen, und die meisten anderen Sprachen haben Sie darin geschult, Einrückungen mit Blöcken und Blöcken mit einer Form der Verschachtelung (entweder explizit oder implizit) zu verknüpfen.

Als Übung habe ich die nicht wesentlichen Klammern aus dem Code entfernt. Sie sollten in der Lage sein, den Code zu lesen und die fehlenden Klammern anzugeben, vorausgesetzt, Sie haben Grundkenntnisse über Elisp (nämlich welche Dinge Funktionen und Werte sind und wie sie aufgebaut sind let*).

custom-set-variables '(linum-format 'dynamic)
defadvice linum-update-window (around linum-dynamic activate)
  let* w length number-to-string
                  + 
                    count-lines (point-min) (point-max) 
                    1       
         linum-format 
           concat " %" (number-to-string w) "d "
     ad-do-it

1
Beachten Sie, dass in Emacs durch Drücken der Tabulatortaste die Einrückung fast immer wie hier beschrieben korrekt gesetzt wird - Sie sollten dies niemals tun, indem Sie Leerzeichen von Hand einfügen!
Tyler

Binde "Cm" an newline-and-indentfür den Emacs-Lisp-Modus und den Lisp-Interaktions-Modus, um dein erstes Beispiel, PythonNut, zu lösen. Und TAB erledigt den Rest der Zeit.
Davor Cubranic

5

Ich schließe dies als eine andere Antwort ein.

Manchmal schlägt die Einrückung fehl. Sie haben dann die Möglichkeit, Folgendes zu verwenden rainbow-delimiters:

Bildbeschreibung hier eingeben

Dies macht die Verschachtelungsebene eines beliebigen Pars explizit und einfach zu scannen.

Es gibt jedoch ein ziemlich großes Problem: Die Eltern lenken lächerlich ab. Hier gibt es ein Gleichgewicht der Betonung. rainbow-delimitersNormalerweise wird auf Kosten des restlichen Codes viel Wert auf die Parens gelegt! Wenn Sie den Regenbogen jedoch mit der Vorderseite nach unten tonen, wird das Scannen zunehmend schwieriger.

Wenn Sie eine Gruppe von Gesichtern finden, die dies gut ausgleicht, dann verwenden Sie sie auf jeden Fall.

Das heißt, eine Lösung (die, die mich vor Freude schnattern lässt) ist, zwei Sätze von Gesichtern zu haben und schnell zwischen ihnen zu wechseln. Wenn Sie andere Dinge tun, werden die Gesichter verdünnt und treten in den Hintergrund:

Bildbeschreibung hier eingeben

Wenn Sie den Punkt jedoch auf eine Paren setzen, werden die Parens gestanzt, sodass Sie die Verschachtelungsebenen sehen können:

Bildbeschreibung hier eingeben

Und hier ist der Code, um das zu tun:

(defvar rainbow-delimiters-switch nil
  "t if rainbow-delimiters are currently punched")
(defvar rainbow-delimiters-face-cookies nil
  "a list of face-remap-add-relative cookies to reset")

(make-variable-buffer-local 'rainbow-delimiters-switch)
(make-variable-buffer-local 'rainbow-delimiters-face-cookies)

(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
(add-hook 'text-mode-hook #'rainbow-delimiters-mode)

(with-eval-after-load 'rainbow-delimiters
  (set-face-foreground 'rainbow-delimiters-depth-1-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-2-face "#9b7b6b")
  (set-face-foreground 'rainbow-delimiters-depth-3-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-4-face "#889899")
  (set-face-foreground 'rainbow-delimiters-depth-5-face "#839564")
  (set-face-foreground 'rainbow-delimiters-depth-6-face "#6391aa")
  (set-face-foreground 'rainbow-delimiters-depth-7-face "#9d748f")
  (set-face-foreground 'rainbow-delimiters-depth-8-face "#7b88a5")
  (set-face-foreground 'rainbow-delimiters-depth-9-face "#659896")

  (defun rainbow-delimiters-focus-on ()
    "Punch the rainbow-delimiters"
    (setq rainbow-delimiters-face-cookies
      (list
        (face-remap-add-relative 'rainbow-delimiters-depth-1-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-1-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-2-face
          '((:foreground "#9B471D") rainbow-delimiters-depth-2-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-3-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-3-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-4-face
          '((:foreground "#3B9399") rainbow-delimiters-depth-4-face))
            (face-remap-add-relative 'rainbow-delimiters-depth-5-face
          '((:foreground "#679519") rainbow-delimiters-depth-5-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-6-face
          '((:foreground "#0E73AA") rainbow-delimiters-depth-6-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-7-face
          '((:foreground "#9D2574") rainbow-delimiters-depth-7-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-8-face
          '((:foreground "#284FA5") rainbow-delimiters-depth-8-face))
        (face-remap-add-relative 'rainbow-delimiters-depth-9-face
          '((:foreground "#199893") rainbow-delimiters-depth-9-face)))
      rainbow-delimiters-switch t))

  (defun rainbow-delimiters-focus-off ()
    "Reset the rainbow-delimiters faces"
    (mapc #'face-remap-remove-relative rainbow-delimiters-face-cookies)
    (setq rainbow-delimiters-switch nil))

  (defun rainbow-delimiters-focus-on-maybe ()
    "Punch the rainbow-delimiters if the point is on a paren"
    (when (looking-at "[][(){}]")
      (unless (or rainbow-delimiters-switch (minibufferp))
        (rainbow-delimiters-focus-on))))

  (defun rainbow-delimiters-focus-off-maybe ()
    "Reset the rainbow-delimiters if the point is not on a paren"
    (unless (looking-at "[][(){}]")
      (when rainbow-delimiters-switch
        (rainbow-delimiters-focus-off))))

  (run-with-idle-timer 0.6 t 'rainbow-delimiters-focus-on-maybe)
  (run-with-idle-timer 0.1 t 'rainbow-delimiters-focus-off-maybe))

Das ist cool! Gibt es einen Grund, warum Sie Regenbogenbegrenzer anstelle von Klammern für Hervorhebungen gewählt haben?
Tyler

@ Tyler kein besonderer Grund, obwohl ich mich jetzt immer noch an Regenbogenbegrenzer halten würde (aber das mag nur daran liegen, dass ich daran gewöhnt bin). Von Highlight-Klammern hatte ich bis vor kurzem einfach nichts gehört.
PythonNut

4

Wenn Sie Ihren Code einrücken, müssen Sie ihn wirklich richtig einrücken. Lisp-Entwickler haben Erwartungen, wie richtig eingerückt aussehen sollte. Dies bedeutet nicht, dass der Code gleich aussieht. Es gibt immer noch verschiedene Möglichkeiten, Code zu formatieren.

  • wie lang soll eine leitung sein
  • Wie verteile ich einen Funktions- / Makroaufruf auf Zeilen?
  • Wie viele Einrückungsbereiche soll es geben?
(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
            ad-do-it))

Ich würde erwarten, dass Einrückungen in irgendeiner Weise eine Eindämmung aufweisen. Aber nicht in deinem Code.

Standardmäßig wird Ihr Code möglicherweise so eingerückt. Andere Antworten beschrieben, wie Sie dies mit Hilfe von Emacs tun können:

(defadvice linum-update-window (around linum-dynamic activate)
  (let* ((w (length (number-to-string
                     (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")))
    ad-do-it))

Ich würde erwarten, dass die letgebundenen Variablen in derselben vertikalen Spalte beginnen. Ich würde auch erwarten, dass der Körper des letweniger eingerückt ist. Wir lernen, wie ein leteingerückt werden soll. Sobald Sie das ein wenig trainiert haben, ist es ein visuelles Muster, das leicht zu erkennen ist.

Die wichtigsten visuellen Bausteine im Code sind defadvice, let*und eine Reihe von Funktionsaufrufen. Das defim Namen sagt mir, dass es sich um eine Definition handelt, gefolgt von einem Namen, einer Argumentliste und einem Text.

So sehe ich gerne

defadvice name arglist
  body

Das let*wäre:, let*eine Liste von Bindungen und ein Körper.

So sehe ich gerne:

let*  list of bindings
  body

Genauer:

let*   binding1
       binding2
       binding3
  body

Für einen Funktionsaufruf möchte ich sehen:

FUNCTIONNAME ARG1 ARG2 ARG3

oder

FUNCTIONNAME ARG1
             ARG2
             ARG3

oder

FUNCTIONNAME
  ARG1
  ARG2
  ARG3

Welche verwendet wird, hängt davon ab, wie lange die Argumente sind. Wir wollen keine zu langen Zeilen machen und jedes Argument in einer eigenen Zeile erlaubt uns, mehr Struktur zu haben.

Sie müssen also Ihren Code unter Verwendung dieser Muster schreiben und sicherstellen, dass der Leser diese Muster in Ihrem Code leicht identifizieren kann.

Klammern sollten ihre Konstrukte direkt einschließen.

(sin 10)

(sin
  10)

Vermeiden Sie Leerzeichen-Beispiele:

(  sin 10  )

oder

(
   sin
)

oder

(sin 10
)

In Lisp haben die Klammern keine sprachliche syntaktische Funktion, sie sind Teil der Syntax der Listendatenstruktur (s-Ausdrücke). So schreiben wir Listen und formatieren die Listen. Für die Formatierung des Listeninhalts verwenden wir Kenntnisse über die Programmiersprache Lisp. Ein letAusdruck sollte anders formatiert sein als ein Funktionsaufruf. Trotzdem sind beide Listen und die Klammern sollten die Listen direkt einschließen. Es gibt einige Beispiele, bei denen es sinnvoll ist, eine einzelne Klammer in einer Zeile zu verwenden, diese jedoch nur selten.

Verwenden Sie die Klammern, um die Ausdrucksgrenzen zu ermitteln. Lassen Sie sich dabei unterstützen, von Liste zu Liste zu wechseln, Listen zu bearbeiten, Listen auszuschneiden und zu kopieren, Listen zu ersetzen, Listen einzurücken / zu formatieren, Listen auszuwählen, ...


2

Verwenden Sie TAB und "CMq" ( indent-pp-sexp) , um grundlegende Hilfe zum Einrücken zu erhalten . newline-and-indentWenn Sie "Cm" eingeben, müssen Sie nach einer neuen Zeile nicht die Tabulatortaste drücken.

Sie können per Sexp mit "CM-links / rechts / hoch / runter / home / Ende" navigieren, was sehr nützlich ist.

Wenn Sie Bedenken haben , das Gleichgewicht in Klammern zu halten, sollten Sie so etwas wie Smartparens verwenden (es ist etwas verzeihender als Paredit , bei dem Sie anfangs das Gefühl haben, eine Zwangsjacke zu tragen). Es kommt auch mit vielen Bindungen zum Navigieren und Bearbeiten auf Sexp-Ebene.

Zum Hervorheben von Parens müssen Sie zunächst die Option aktivieren (Menü "Optionen" -> Übereinstimmende Klammern hervorheben oder show-paren-mode). Sie können auch eines der Pakete verwenden, die in der Gesetzesliste in seinem Kommentar aufgeführt sind, z ".


1

Als Ergänzung zu dem, was andere als Antworten gegeben haben, sind hier meine 2 Cent:

  • Die automatische Einrückung durch emacs-lisp-modeist unerlässlich.
  • blink-matching-parenist nilstandardmäßig aktiviert (nicht aktiviert). Lass es so.
  • Ich benutze show-paren-mode, um den linken Paren zu markieren, der dem rechten Paren vor dem Cursor entspricht.
  • Ich lösche vorübergehend den rechten Paren vor dem Cursor und tippe ihn erneut ein, wenn ich besser sehen möchte, wo sich der passende linke Paren befindet.

Ich benutze kein elektrisches Pairing oder Regenbogen oder eine andere solche "Hilfe". Für mich ist das eine Mühe, keine Hilfe.

Insbesondere electric-pair-modeist für mich eine unbequeme Mühe. Aber manche Leute lieben es. Und ich stelle mir vor, dass es in einigen anderen Paarkontexten als in Lisp-Klammern hilfreich sein könnte (ich stelle mir das vor, bin aber auch nicht überzeugt von solchen Anwendungsfällen).

Sie finden, was für Sie am besten funktioniert. Die wichtigsten Dinge, die ich sagen möchte, sind: (1) Automatische Einrückung ist Ihr Freund, ebenso wie eine Möglichkeit, den linken Elternteil zu erkennen, der mit dem rechten Elternteil vor dem Punkt übereinstimmt.

Insbesondere wenn Sie sehen, was der automatische Einzug für Sie bewirkt, werden Sie sofort darauf hingewiesen, dass Sie die richtigen Parens nie wieder selbst in eine Zeile setzen möchten. Dieser Codierungsstil, der in anderen Sprachen allgegenwärtig ist, ist nur verrauscht.

Neben der automatischen Einrückung, die Sie mit RETund erhalten TAB, können Sie diese auch bequem verwenden C-M-q. (Verwenden Sie C-h kin emacs-lisp-mode, um herauszufinden, was diese Schlüssel bewirken.)


0

Ich habe bemerkt, dass einige Leute bereits Regenbogen-Trennzeichen erwähnt haben, das ist auch mein Lieblingsmodus beim Editieren von Lisp-Code.

Eigentlich liebe ich Klammern, das Beste an Lisp sind diese Klammern, es macht Spaß, mit ihnen umzugehen, wenn man weiß, wie man es macht:

  • Installieren Sie Evil-Mode und sein Plugin Evil-Surround, damit Sie Klammern leicht bearbeiten können. Drücken Sie beispielsweise, ci(um alles darin zu entfernen (), va(und wählen Sie das von "()" und "()" umhüllte Element aus. und Sie können drücken, %um zwischen den übereinstimmenden Klammern zu springen

  • Verwenden Sie Flycheck oder Flymake. Nicht passende Klammern werden in Echtzeit unterstrichen


0

Die Schwierigkeit hierbei ist, dass Sie vor und nach einem bestimmten Code einen Code hinzufügen möchten sexp. In dieser Situation ist der Sexp (concat " %" (number-to-string w) "d "). Sie möchten die if-Anweisung (if (> w 1) davor und die else-Anweisung " %2d ") danach einfügen .

Ein Hauptteil der Schwierigkeit besteht darin , dies zu isolieren.sexp Ich persönlich benutze den folgenden Befehl, um a zu isolierensexp

(defun isolate-sexp () (interactive)
       (save-excursion (forward-sexp) (if (not (eolp-almost))
               (split-line) nil)))
(defun eolp-almost () (interactive)
(save-excursion (while (equal (char-after) ? ) (forward-char 1))
        (if (eolp) t nil )      ))

Setzen Sie den Cursor einfach an den Anfang von (concat " %" (number-to-string w) "d "), dh an den ersten (, und wenden Sie dann das Obige an isolate-sexp. Sie erhalten

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (concat " %" (number-to-string w) "d ")
                                  ))
            ad-do-it))

Fügen Sie dann davor und danach den entsprechenden Code hinzu sexp, d. H

(defadvice linum-update-window (around linum-dynamic activate)
   (let* ((w (length (number-to-string
      (+ (count-lines (point-min) (point-max)) 1))))
         (linum-format (if (> w 1) (concat " %" (number-to-string w) "d ") " %2d ")
                                  ))
            ad-do-it))

Und voila. Der so erhaltene Code ist vielleicht nicht schön, aber die Chance, sich zu verirren, ist geringer.

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.