Як замінити елемент аліста?


36

У мене це є за замовчуванням у моїх auto-mode-alist:

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

(навіть з emacs -Q). Я хотів би замінити js2-modeна javascript-mode. Звичайно, я міг би скористатися assq-delete-allі add-to-listзнову, але мені цікаво, чи немає кращого способу.

Редагувати: явно не хочу використовувати налаштування, я віддаю перевагу самому майструвати init.el.

Відповіді:


37

Хоча відповідь @ Dan є прекрасним рішенням, вона непотрібна. Однією з причин, що Emacs використовує аліст тут, є те, що за допомогою списку ви можете просто додати новий елемент на передню частину списку, і це затінить збіги далі за списком .

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

1
Хочете сказати, чому голова?
Дрю

1
Я підтримав вашу відповідь - дякую, це добре знати. Я думаю, що низовик вважав це рішення неелегантним (мушу сказати, що я згоден, хоча не вважаю це причиною заборони - адже він обидва вирішує мою проблему і є цінною інформацією!)
mbork

7
Справді, він не відповідає на питання, як замінити . Його сенс полягає в тому, що вам не потрібно замінювати (якщо тільки у вас є якась інша потреба, ніж те, що ви описали).
Дрю

2
питання насправді було не про заміну в технічному сенсі, а про зміну в сенсі вищого рівня.
Ерік Аллик

2
Це завжди спрацює, незалежно від того, чи є мінуси в чистому просторі, або буде видалено в будь-якій майбутній версії.
politza

33

Використовуйте setfдля зміни значення на місці:

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

Якщо ви хочете замінити значення у списку, то setfце узагальнене обладнання, яке вам потрібно зробити для цього. Більш ідіоматичний спосіб впоратися з цим auto-mode-alistдив. У відповіді @ Дрю (та його поясненні відтінення).


Ого. Зараз я почуваюся дурним. Спасибі! (І ідея (майже) кожного місця, де можна мати setfзмогу, справді має бути показана хлопцям Java.)
mbork

6
@mbork Можливо, вам сподобається це класичне пояснення хлопцям Perl. list.warhead.org.uk/pipermail/iwe/2005-July/000130.html
purple_arrows

@mbork: насправді немає причин відчувати себе дурним - setfвикористовується весь час у Common Lisp, але ви натрапляєте на нього набагато рідше в Elisp.
Дан

@Dan: правда. Тепер мені цікаво, чому Елісп використовує setfтак рідко, порівняно з CL ...
mbork

19

Ймовірно, найшвидший спосіб змінити клітинку проти setcdr

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

(setcdr CELL NEWCDR)

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

Варто зауважити, що setfце неможливо у старшому Emacsen, але 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))

Чи знаєте ви, яку версію Emacs додав setf?
dshepherd

1
@dsheperd не від руки, ні. Чому потрібно знати? Я б сказав, що будь-які emacs, які повинні бути націлені на нову розробку, матимуть setf, але можливо не буде оброблятися для неї типом даних, які ви хочете встановити. Їх називають узагальненими змінними .
Шон Аллред

Я хотів знати, чи нормально використовувати setf в якомусь новому коді, але, як ви сказали, виявляється, що узагальненої змінної для того, чого я хотів, поки що занадто недавна версія все одно не було.
дшеферд

5

ОП вимагає рішення, яке обробляє списки, які містять рядкові клавіші. Щоб вирішити це, дивіться це питання . Якщо випадково вам потрібно обробляти списки лише символьними клавішами, то з Emacs 25 ви можете використовувати:

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

замінити компакт-диск. Якщо у вас є доступ до Emacs 26, ця методика працює з рядковими клавішами:

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

Зауважте, що в Emacs 26 також є інші способи обробки струнних клавіш; див. це питання, як згадувалося вище.


(setf (alist-get "\\.js\\'" auto-mode-alist nil nil #'equal) 'js2-mode)повинен працювати (хоча Emacs 26 хоча).
npostavs

@RadonRosborough: є функція редагування. Подумайте, щоб виправити вашу відповідь.
антоніо

Ви використовуєте alist-getрядок "\\.js\\'", але alist-getзаснована на assq, тому вона не працюватиме з рядком, як ви заявляєте у своїй відповіді.
Антоніо

@antonio О так, ви абсолютно праві. Я не зрозумів, що поставлене запитання насправді вимагає рішення, яке обробляє рядкові клавіші. Я зроблю редагування, дякую!
Радон Росборо

2

Якщо ви знаєте, що більше ніколи не будете використовувати javascript-режим, не торкайтеся автоматичного режиму і додайте його до свого init.el

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

1
Насправді, насправді немає javascript-mode: javascript-modeце лише псевдонім для js-mode(за замовчуванням), і це було зроблено саме таким чином, щоб користувачі могли робити те, що ви пропонуєте, якщо вони бажають js2-mode(не втрачаючи можливості користуватися, js-modeякщо хочуть).
Стефан

Я отримав свою відповідь з звички псевдоніму для cperl-режиму та nxml-режиму. То що б тут зробити трюк? (defalias 'js-mode' js2-mode)?
Маттіас

1
Ти неправильно мене зрозумів. Я кажу, що ваша відповідь абсолютно правильна і не заважає вам використовувати режим "javascript", оскільки те, що ви називаєте цим ім'ям, насправді js-mode(всупереч тому, що відбувається perl-mode, наприклад).
Стефан

Зрозумів ... (випадковий користувач режиму javascript тут)
Маттіас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.