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))
quelle
%2d
da die Breite von rechtsbündig nach linksbündig wechselt, sobald sie sich auf 3 oder mehr Zeichen bewegt.highlight-parentheses
.rainbow-delimiters
; usw. Hier ist meine eigene vereinfachte Versionhighlight-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.Antworten:
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-b
vorwärts / rückwärts bewegen durch sexpC-M-n
/C-M-p
vorwärts / rückwärts durch Liste bewegenC-M-u
/C-M-d
um eine Ebene hoch / runter zu gehenC-M-t
die zwei Sexps um Punkt zu tauschenC-M-k
ein sexp tötenC-M-SPC
ein sexp markierenC-M-q
ein Geschlecht neu einrückenDer Beispielcode, den Sie angegeben haben, ist möglicherweise klarer, wenn Sie den Einzug korrigieren: Setzen Sie den Punkt an den Anfang von
(defadvice...
undC-M-q
drü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 undC-M-o
die 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 anshow-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.
quelle
C-M-q
mit 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 immerC-x u
rückgängig machen).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.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 inlispy
entweder 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
()
, drücken Sie (.if
.()
.> w 10
.Schritt 4
So klonen Sie den String:
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:
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: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.
quelle
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:
Angenommen, das
1
ist wirklich ein großer Ausdruck, und Sie möchten ihn in einer eigenen Zeile einrücken.Das ist irreführend.
1
wird nur ein Slot eingerückt, obwohl es sich um ganze drei Verschachtelungsebenen höher handelt! Besser von seinen Eltern.Wenn wir dieses Schema für Ihren eigenen Code verwenden, erhalten wir Folgendes:
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*
).quelle
newline-and-indent
fü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.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
: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-delimiters
Normalerweise 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:
Wenn Sie den Punkt jedoch auf eine Paren setzen, werden die Parens gestanzt, sodass Sie die Verschachtelungsebenen sehen können:
Und hier ist der Code, um das zu tun:
quelle
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.
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:
Ich würde erwarten, dass die
let
gebundenen Variablen in derselben vertikalen Spalte beginnen. Ich würde auch erwarten, dass der Körper deslet
weniger eingerückt ist. Wir lernen, wie einlet
eingerü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. Dasdef
im Namen sagt mir, dass es sich um eine Definition handelt, gefolgt von einem Namen, einer Argumentliste und einem Text.So sehe ich gerne
Das
let*
wäre:,let*
eine Liste von Bindungen und ein Körper.So sehe ich gerne:
Genauer:
Für einen Funktionsaufruf möchte ich sehen:
oder
oder
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.
Vermeiden Sie Leerzeichen-Beispiele:
oder
oder
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
let
Ausdruck 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, ...
quelle
Verwenden Sie TAB und "CMq" (
indent-pp-sexp
) , um grundlegende Hilfe zum Einrücken zu erhalten .newline-and-indent
Wenn 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 ".quelle
Als Ergänzung zu dem, was andere als Antworten gegeben haben, sind hier meine 2 Cent:
emacs-lisp-mode
ist unerlässlich.blink-matching-paren
istnil
standardmäßig aktiviert (nicht aktiviert). Lass es so.show-paren-mode
, um den linken Paren zu markieren, der dem rechten Paren vor dem Cursor entspricht.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-mode
ist 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
RET
und erhaltenTAB
, können Sie diese auch bequem verwendenC-M-q
. (Verwenden SieC-h k
inemacs-lisp-mode
, um herauszufinden, was diese Schlüssel bewirken.)quelle
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 springenVerwenden Sie Flycheck oder Flymake. Nicht passende Klammern werden in Echtzeit unterstrichen
quelle
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
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 anisolate-sexp
. Sie erhaltenFügen Sie dann davor und danach den entsprechenden Code hinzu
sexp
, d. HUnd voila. Der so erhaltene Code ist vielleicht nicht schön, aber die Chance, sich zu verirren, ist geringer.
quelle