Come sostituire un elemento di un elenco?


36

Ho questo di default nel mio auto-mode-alist:

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

(anche con emacs -Q). Mi piacerebbe sostituire js2-modeper javascript-mode. Certo, potrei usare assq-delete-alle poi di add-to-listnuovo, ma mi chiedo se non c'è un modo migliore.

Modifica: esplicitamente non voglio usare Personalizza, preferisco creare il mio init.elme stesso.

Risposte:


37

Mentre la risposta di @ Dan è una soluzione perfettamente valida, non è necessaria. Uno dei motivi per cui Emacs usa una lista qui è che con una lista puoi semplicemente aggiungere un nuovo elemento in cima alla lista e ombreggerà le corrispondenze più in basso nella lista .

(add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode))

1
Vuoi dire perché il downvote?
Disegnato l'

1
Ho votato a favore della tua risposta - grazie, è bello saperlo. Immagino che il downvoter abbia ritenuto questa soluzione inelegante (devo dire che sono d'accordo, anche se non lo considero un motivo per il downvoting - dopo tutto, entrambi risolve il mio problema ed è un'informazione preziosa!)
mbork

7
Certo, non risponde alla domanda su come sostituire . Il punto è che non è necessario sostituirlo (a meno che non si abbia qualche altra necessità rispetto a quella descritta).
Disegnato l'

2
la domanda non riguardava davvero la sostituzione in senso tecnico, ma piuttosto il cambiamento in senso superiore.
Erik Kaplun,

2
Funzionerà sempre, indipendentemente dal fatto che i contro siano nello spazio puro o saranno rimossi in una versione futura.
politza,

33

Utilizzare setfper modificare il valore in atto:

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

Se vuoi sostituire un valore nell'elenco, allora setfè il macchinario generalizzato che devi fare. Per il modo più idiomatico di affrontare la auto-mode-alist, vedi la risposta di @ Drew (e la sua spiegazione dell'ombra).


Wow. Mi sento stupido ora. Grazie! (E l'idea di (quasi) ogni luogo per setfpoter davvero essere mostrata ai ragazzi di Java.)
mbork,

6
@mbork Potresti apprezzare questa classica spiegazione ai ragazzi del Perl. lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html
purple_arrows

@mbork: davvero nessun motivo per sentirsi sciocchi - setfè usato tutto il tempo in Common Lisp, ma ci si imbatte molto meno frequentemente in elisp.
Dan

@Dan: true. Ora mi chiedo perché Elisp usi setfcosì di rado, rispetto a CL ...
mbork,

19

Il modo più veloce per cambiare effettivamente la cella contro è probabilmente setcdr

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

(setcdr CELL NEWCDR)

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

Vale la pena notare che setfnon è disponibile nella vecchia Emacsen, ma lo 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))

Ti capita di sapere quale versione di Emacs è stata aggiunta setf?
pastore,

1
@dsheperd non fuori mano, no. Perché hai bisogno di sapere? Direi che qualsiasi emac che dovrebbe essere preso di mira per il nuovo sviluppo avrà setf, ma potrebbe non esserci gestione per il tipo di dati che si desidera impostare. Si chiamano variabili generalizzate .
Sean Allred,

Volevo sapere se era giusto usare setf in qualche nuovo codice, ma come hai detto, non c'era una variabile generalizzata per quello che volevo fino a una versione troppo recente comunque.
pastore

5

L'OP richiede una soluzione che gestisca gli elenchi con chiavi stringa. Per gestirlo, vedi questa domanda . Se per caso hai solo bisogno di gestire gli elenchi con i tasti simbolo, a partire da Emacs 25 puoi usare:

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

per sostituire un CDR. Se hai accesso a Emacs 26, questa tecnica funziona con le chiavi di stringa, come segue:

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

Si noti che ci sono anche altri modi in Emacs 26 per gestire le chiavi di stringa; vedi questa domanda come menzionato sopra.


(setf (alist-get "\\.js\\'" auto-mode-alist nil nil #'equal) 'js2-mode)dovrebbe funzionare (richiede Emacs 26).
npostavs,

@RadonRosborough: c'è una funzione di modifica. Considera di risolvere la tua risposta.
antonio,

Stai usando alist-getcon la stringa "\\.js\\'", ma alist-getè basato su assq, quindi non funzionerà con una stringa come rivendichi nella tua risposta.
antonio

@antonio Oh sì, hai perfettamente ragione. Non mi ero reso conto che la domanda come pubblicata in realtà richiede una soluzione che gestisce le chiavi di stringa. Farò la modifica, grazie!
Radon Rosborough,

2

Se sai che non utilizzerai mai più la modalità javascript, lascia che la modalità automatica non venga toccata e aggiungi al tuo init.el

  (defalias 'javascript-mode 'js2-mode "Some handy explanation goes here.")

1
In realtà, non c'è javascript-mode, davvero: javascript-modeè solo un alias per js-mode(per impostazione predefinita) ed è stato fatto in questo modo in modo specifico in modo che gli utenti possano fare come te suggeriscono se preferiscono js2-mode(senza perdere la possibilità di utilizzare js-modese lo desiderano).
Stefan,

Ho ricavato la mia risposta dall'abitudine di aliasing per la modalità cperl e la modalità nxml. Quindi cosa farebbe il trucco qui? (defalias 'js-mode' js2-mode)?
Matthias,

1
Mi hai frainteso. Sto dicendo che la tua risposta è esatta e non ti impedisce di utilizzare la "modalità javascript" poiché ciò che chiami con quel nome è davvero js-mode(contrariamente a ciò che accade perl-modeper esempio).
Stefan,

Capito ... (utente casuale in modalità javascript qui)
Matthias,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.