Làm thế nào để thay thế một yếu tố của một alist?


36

Tôi có cái này theo mặc định trong auto-mode-alist:

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

(thậm chí với emacs -Q). Tôi muốn thay thế js2-modecho javascript-mode. Tất nhiên, tôi có thể sử dụng assq-delete-allvà sau đó add-to-listmột lần nữa, nhưng tôi tự hỏi liệu không có cách nào tốt hơn.

Chỉnh sửa: Tôi rõ ràng không muốn sử dụng Tùy chỉnh, tôi thích tự làm thủ công hơn init.el.

Câu trả lời:


37

Mặc dù câu trả lời của @ Dan là một giải pháp hoàn toàn tốt, nhưng nó không cần thiết. Một trong những lý do Emacs sử dụng một alist ở đây là với một alist bạn có thể chỉ cần thêm một phần tử mới vào phía trước danh sách và nó sẽ tạo bóng phù hợp hơn nữa trong danh sách .

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

1
Quan tâm để nói tại sao các downvote?
vẽ

1
Tôi nêu lên câu trả lời của bạn - cảm ơn, thật tốt khi biết. Tôi đoán rằng downvoter nghĩ rằng giải pháp này không phù hợp (tôi phải nói rằng tôi đồng ý, mặc dù không coi đó là một lý do để hạ thấp - sau tất cả, nó giải quyết vấn đề của tôi và là một thông tin có giá trị!)
mbork

7
Phải thừa nhận rằng nó không trả lời câu hỏi làm thế nào để thay thế . Quan điểm của nó là bạn không cần phải thay thế (trừ khi bạn có một số nhu cầu khác ngoài những gì bạn mô tả).
vẽ

2
câu hỏi không thực sự là về việc thay thế theo nghĩa kỹ thuật mà là thay đổi theo nghĩa cấp cao hơn.
Erik Allik

2
Điều này sẽ luôn hoạt động bất kể là khuyết điểm ở trong không gian thuần túy hay sẽ bị xóa trong một số phiên bản trong tương lai.
Politza

33

Sử dụng setfđể thay đổi giá trị tại chỗ:

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

Nếu bạn muốn thay thế một giá trị trong danh sách, thì setfmáy móc tổng quát bạn cần phải làm như vậy. Để biết cách đối phó hơn auto-mode-alist, hãy xem câu trả lời của @ Drew (và lời giải thích của anh ấy về bóng tối).


Ồ Tôi cảm thấy ngu ngốc bây giờ. Cảm ơn! (Và ý tưởng về (hầu hết) mọi nơi để có setfthể thực sự được hiển thị cho những người Java.)
mbork

6
@mbork Bạn có thể thưởng thức lời giải thích kinh điển này cho các chàng trai Perl. lists.warhead.org.uk/pipermail/iwe/2005-July/000130.html
purple_arrows

@mbork: thực sự không có lý do gì để cảm thấy ngớ ngẩn - setfđược sử dụng mọi lúc trong Common Lisp, nhưng bạn chạy qua nó ít thường xuyên hơn trong elisp.
Dan

@Dan: đúng. Bây giờ tôi đang tự hỏi tại sao Elisp sử dụng setfrất hiếm khi, so với CL ...
mbork

19

Cách nhanh nhất để thực sự thay đổi tế bào khuyết điểm có lẽ là setcdr

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

(setcdr CELL NEWCDR)

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

Điều đáng chú ý setflà không có sẵn ở Emacsen cũ, nhưng setcdrlà.


*** 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))

Bạn có biết phiên bản Emacs nào được thêm vào setfkhông?
dshepherd

1
@dsheperd không ra tay, không. Tại sao bạn cần phải biết? Tôi muốn nói rằng bất kỳ emacs nào nên được nhắm mục tiêu cho phát triển mới sẽ có setf, nhưng có thể không xử lý nó cho loại dữ liệu bạn muốn đặt. Chúng được gọi là các biến tổng quát .
Sean Allred

Tôi muốn biết liệu có ổn không khi sử dụng setf trong một số mã mới, nhưng như bạn đã nói, hóa ra không có biến tổng quát cho những gì tôi muốn cho đến khi phiên bản quá gần đây.
dshepherd

5

OP yêu cầu một giải pháp xử lý các liên kết có khóa chuỗi. Để xử lý điều đó, xem câu hỏi này . Nếu tình cờ bạn chỉ cần xử lý các liên kết với các phím biểu tượng, thì kể từ Emacs 25, bạn có thể sử dụng:

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

để thay thế một cdr. Nếu bạn có quyền truy cập vào Emacs 26, kỹ thuật này hoạt động với các phím chuỗi, như sau:

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

Lưu ý rằng cũng có những cách khác trong Emacs 26 để xử lý các khóa chuỗi; xem câu hỏi này như đã đề cập ở trên


(setf (alist-get "\\.js\\'" auto-mode-alist nil nil #'equal) 'js2-mode)nên hoạt động (yêu cầu Emacs 26 mặc dù).
npostavs

@RadonRosborough: có một tính năng chỉnh sửa. Xem xét để sửa bạn trả lời.
antonio

Bạn đang sử dụng alist-getvới chuỗi "\\.js\\'", nhưng alist-getdựa trên assq, vì vậy nó sẽ không hoạt động với chuỗi như bạn yêu cầu trong câu trả lời của mình.
antonio

@antonio Ồ vâng, bạn hoàn toàn chính xác. Tôi đã không nhận ra rằng câu hỏi như được đăng thực sự đòi hỏi một giải pháp xử lý các khóa chuỗi. Tôi sẽ thực hiện chỉnh sửa, cảm ơn!
Radon Rosborough

2

Nếu bạn biết bạn sẽ không sử dụng chế độ javascript nữa, hãy để chế độ tự động không bị ảnh hưởng và thêm vào init.el của bạn

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

1
Trên thực tế, không có javascript-mode, thực sự: javascript-modechỉ là một bí danh cho js-mode(theo mặc định) và nó được thực hiện theo cách này một cách cụ thể để người dùng có thể làm như bạn đề xuất nếu họ thích js2-mode(mà không mất khả năng sử dụng js-modenếu họ muốn).
Stefan

Tôi bắt nguồn câu trả lời của mình từ thói quen răng cưa cho chế độ cperl và chế độ nxml. Vì vậy, những gì sẽ làm thủ thuật ở đây? (defalias 'js-mode' js2-mode)?
Matthias

1
Bạn đã hiểu nhầm tôi. Tôi đang nói rằng câu trả lời của bạn là hoàn toàn chính xác và không ngăn bạn sử dụng "chế độ javascript" vì những gì bạn gọi bằng tên đó thực sự là js-mode( perl-modeví dụ như những gì xảy ra ).
Stefan

Hiểu rồi ... (người dùng chế độ javascript thông thường ở đây)
Matthias
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.