Wie ersetze ich ein Element einer Liste?

36

Ich habe dies standardmäßig in meinem auto-mode-alist:

("\\.js\\'" . javascript-mode)

(auch mit emacs -Q). Ich möchte als Ersatz js2-modefür javascript-mode. Natürlich könnte ich assq-delete-allund dann add-to-listwieder verwenden, aber ich frage mich, ob es keinen besseren Weg gibt.

Bearbeiten: Ich möchte Anpassen ausdrücklich nicht verwenden, ich bastle lieber init.elselbst.

mbork
quelle

Antworten:

37

Die Antwort von @ Dan ist zwar eine perfekte Lösung, aber nicht notwendig. Einer der Gründe, warum Emacs hier eine Alist verwendet , besteht darin, dass Sie mit einer Alist einfach ein neues Element an der Vorderseite der Liste hinzufügen können, das Übereinstimmungen weiter unten in der Liste spiegelt .

(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))
Drew
quelle
1
Möchtest du sagen, warum die Ablehnung?
Drew
1
Ich habe Ihre Antwort positiv bewertet - danke, es ist gut zu wissen. Ich denke, der Downvoter hat diese Lösung für unelegant befunden (ich muss sagen, dass ich zustimme, sehe sie jedoch nicht als Grund für eine Downvotierung an - schließlich löst sie mein Problem und ist eine wertvolle Information!)
mbork
7
Zugegeben, es beantwortet nicht die Frage, wie man ersetzt . Der Punkt ist, dass Sie nicht ersetzen müssen (es sei denn, Sie haben einen anderen Bedarf als den, den Sie beschrieben haben).
Drew
2
es ging nicht wirklich darum, im technischen sinne zu ersetzen, sondern sich im übergeordneten sinn zu verändern.
Erik Allik
2
Dies funktioniert immer, egal ob sich die Nachteile im reinen Raum befinden oder in einer zukünftigen Version entfernt werden.
Politza
33

Verwenden Sie setf, um den Wert zu ändern:

(setf (cdr (rassoc 'javascript-mode auto-mode-alist)) 'js2-mode)

Wenn Sie einen Wert in der Liste ersetzen möchten , setfist dies die verallgemeinerte Maschinerie, die Sie dazu benötigen. Informationen zur idiomatischeren Vorgehensweise finden Sie in auto-mode-alistder Antwort von @ Drew (und in der Erklärung zum Shadowing).

Dan
quelle
Wow. Ich fühle mich jetzt dumm. Vielen Dank! (Und die Idee von (fast) jedem Ort in der setfLage zu sein, sollte wirklich Java-Jungs gezeigt werden.)
mbork
6
@mbork Diese klassische Erklärung könnte den Perl-Leuten gefallen. lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html
purple_arrows
@mbork: Wirklich kein Grund, sich albern zu fühlen - setfwird in Common Lisp die ganze Zeit verwendet, aber in elisp stößt man viel seltener darauf.
Dan
@ Dan: wahr. Jetzt frage ich mich, warum Elisp im setfVergleich zu CL ...
mbork 13.11.14
19

Der schnellste Weg, um tatsächlich die Nachteile der Zelle zu ändern, ist wahrscheinlich setcdr

setcdr is a built-in function in `C source code'.

(setcdr CELL NEWCDR)

Set the cdr of CELL to be NEWCDR.  Returns NEWCDR.

Es ist erwähnenswert, dass setfes in älteren Emacsen nicht verfügbar ist, aber setcdr.


*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (setq tmp '((one . 1) (two . 2) (three . 4)))
((one . 1)
 (two . 2)
 (three . 4))

ELISP> (setcdr (assq 'three tmp) 3)
3 (#o3, #x3, ?\C-c)
ELISP> tmp
((one . 1)
 (two . 2)
 (three . 3))
Sean Allred
quelle
Weißt du zufällig, welche Version von Emacs hinzugefügt wurde setf?
Dshepherd
1
@dsheperd nicht von der Hand, nein. Warum willst du das wissen? Ich würde sagen, dass alle Emacs, die für die Neuentwicklung ausgewählt werden sollen, setf haben, aber für die Art von Daten, die Sie festlegen möchten, wird es möglicherweise keine Behandlung dafür geben. Sie werden verallgemeinerte Variablen genannt .
Sean Allred
Ich wollte wissen, ob es in Ordnung ist, setf in einem neuen Code zu verwenden, aber wie Sie sagten, stellte sich heraus, dass es ohnehin keine verallgemeinerte Variable für das gab, was ich wollte, bis auf eine zu aktuelle Version.
Dshepherd
5

Das OP fragt nach einer Lösung, die Alisten mit String-Schlüsseln behandelt. Sehen Sie sich dazu diese Frage an . Wenn Sie zufällig nur mit Alisten mit Symbolschlüsseln umgehen müssen, können Sie ab Emacs 25 Folgendes verwenden:

(setf (alist-get <key> <alist>) <value>)

eine cdr ersetzen. Wenn Sie Zugriff auf Emacs 26 haben, funktioniert diese Technik mit Zeichenfolgenschlüsseln wie folgt:

(setf (alist-get "\\.js\\'" auto-mode-alist nil nil #'equal) 'js2-mode)

Beachten Sie, dass es in Emacs 26 auch andere Möglichkeiten gibt, mit String-Schlüsseln umzugehen. siehe diese Frage wie oben erwähnt.

Radon Rosborough
quelle
(setf (alist-get "\\.js\\'" auto-mode-alist nil nil #'equal) 'js2-mode)sollte funktionieren (erfordert allerdings Emacs 26).
Npostavs
@RadonRosborough: Es gibt eine Bearbeitungsfunktion. Erwägen Sie, Ihre Antwort zu korrigieren.
Antonio
Sie verwenden alist-getmit der Zeichenfolge "\\.js\\'", alist-getbasieren jedoch auf assq, sodass sie nicht mit einer Zeichenfolge funktioniert, wie Sie in Ihrer Antwort angeben.
Antonio
@antonio Oh ja, du hast vollkommen recht. Mir war nicht klar, dass für die gestellte Frage tatsächlich eine Lösung erforderlich ist, die sich mit String-Schlüsseln befasst. Ich werde die Bearbeitung machen, danke!
Radon Rosborough
2

Wenn Sie wissen, dass Sie den JavaScript-Modus nie wieder verwenden werden, lassen Sie den automatischen Modus-Alist unberührt und ergänzen Sie ihn zu Ihrem init.el

  (defalias 'javascript-mode 'js2-mode "Some handy explanation goes here.")
Matthias
quelle
1
Eigentlich gibt es eigentlich keinen javascript-mode: Es javascript-modegibt nur einen Alias ​​für js-mode(standardmäßig) und dieser wurde speziell so erstellt, dass die Benutzer Ihren Vorschlägen folgen können, wenn sie dies bevorzugen js2-mode(ohne die Fähigkeit zu verlieren, ihn zu verwenden, js-modewenn sie dies möchten).
Stefan
Ich habe meine Antwort von der Gewohnheit des Aliasing für den cperl-Modus und den nxml-Modus abgeleitet. Also, was würde der Trick hier tun? (defalias 'js-mode' js2-mode)
Matthias
1
Du hast mich misverstanden. Ich sage, dass Ihre Antwort genau richtig ist und Sie nicht daran hindert, den "Javascript-Modus" zu verwenden, da das, was Sie bei diesem Namen nennen, wirklich ist js-mode(im Gegensatz zu dem, was perl-modezum Beispiel passiert ).
Stefan
Matthias