如何替换列表元素?


36

默认情况下,我在auto-mode-alist

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

(即使使用emacs -Q)。我想替代js2-modejavascript-mode。当然,我可以使用assq-delete-all,然后add-to-list再次,但我不知道是否有没有更好的办法。

编辑:我明确不想使用自定义,我更喜欢init.el自己动手。

Answers:


37

尽管@Dan的答案是一个很好的解决方案,但这不是必需的。Emacs 在这里使用alist的原因之一是,有了alist,您可以简单地将一个新元素添加到列表的前面,它将在列表的下方阴影匹配

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

1
小心地说为什么要投票?
德鲁

1
我支持您的回答-谢谢,很高兴知道。我猜低估者认为此解决方案不太理想(我不得不说我同意,尽管不认为这是低估的原因-毕竟,这既解决了我的问题,又是有价值的信息!)
mbork

7
诚然,它没有回答如何替换的问题。其要点是您不需要替换(除非您有其他需求,而不是您描述的需求)。
Drew

2
问题不是在技​​术上真正地替代,而是在更高层次上进行改变。
Erik Allik

2
无论缺点是在纯净空间中还是将在以后的版本中删除,这将始终有效。
politza '16

33

使用setf到位,以改变该值:

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

如果要替换列表中的值,则setf需要使用通用机制。有关处理的更惯用的方法auto-mode-alist,请参见@Drew的答案(以及他对阴影的解释)。


哇。我现在觉得很蠢。谢谢!(几乎所有地方都可以使用的想法setf应该向Java专家展示。)
mbork 2014年

6
@mbork您可能会喜欢Perl家伙的经典解释。 listing.warhead.org.uk/pipermail/iwe/2005-July/000130.html
purple_arrows 2014年

@mbork:真的没有理由感到愚蠢- setf在Common Lisp中一直使用它,但是在elisp中遇到它的频率要低得多。

@丹:是的。现在我想知道为什么setf与CL相比,Elisp 很少使用...
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,但是正如您所说的那样,直到最近的版本,我想要的东西都没有通用变量。
dshepherd

5

OP要求一种解决方案,该解决方案处理具有字符串键的列表。要解决这个问题,请参阅此问题。如果偶然地您只需要使用符号键来处理列表,那么从Emacs 25开始,您可以使用:

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

更换cdr。如果您可以访问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-getstring "\\.js\\'",但是 alist-get基于assq,因此您在答案中声明的字符串将无法使用。
安东尼奥18-3-2

@antonio哦,是的,你是完全正确的。我没有意识到发布的问题实际上确实需要一个处理字符串键的解决方案。我将进行编辑,谢谢!
Radon Rosborough,

2

如果您知道您将不再使用javascript-mode,请让auto-mode-alist保持不变并添加到您的init.el中

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

1
实际上,没有javascript-mode,真的: javascript-mode只是js-mode(默认情况下)的别名,它是专门通过这种方式完成的,以便用户可以根据自己的喜好,按照您的建议进行操作(如果愿意js2-mode,不会失去使用能力js-mode)。
Stefan's

我的答案来自对cperl-mode和nxml-mode别名的习惯。那么,这里的窍门是什么?(defalias'js-mode'js2-mode)?
马赛厄斯

1
你误解我了。我的意思是您的答案是完全正确的,并且不会阻止您使用“ javascript-mode”,因为您使用该名称进行的调用确实是正确的js-mode(例如,与之相反perl-mode)。
Stefan's

知道了...(这里是javascript模式的随机用户)
Matthias
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.