Emacs desktop-save-mode和autoload冲突
问题: 开启desktop-save-mode之后, 连不上CLojure REPL, 提示
Key sequence C-c M-j starts with non-prefix key C-c
查看了一下cider的代码的确有下面的代码
;;;###autoload (eval-after-load 'clojure-mode '(progn (define-key clojure-mode-map (kbd "C-c M-j") 'cider-jack-in) (define-key clojure-mode-map (kbd "C-c M-c") 'cider-connect)))
同时我自己也写了一个hook
(add-hook 'clojure-mode-hook (lambda () (define-key clojure-mode-map "\C-c" 'kill-ring-save) ) )
但是让我不解的的, 没有开启desktop-save-mode也是同样的东西, 但是并没有问题.
猜测原因是谁先谁后的问题, hook先执行, 那么后面的define-key就会出现non prefix的错误, 但是如果eval-after-load先执行, 则没有此问题. 分别打开和关闭desktop-save-mode的情况下打印clojure-mode-map的内容如下
ELISP> clojure-map *** Eval error *** Symbol's value as variable is void: clojure-map ELISP> clojure-mode-map (keymap (3 . kill-ring-save) ; 开启desktop-save-mode (menu-bar keymap (Clojure menu-item "Clojure" (keymap "Clojure" (Toggle\ between\ string\ &\ keyword menu-item "Toggle between string & keyword" clojure-toggle-keyword-string) (Mark\ string menu-item "Mark string" clojure-mark-string) (Insert\ ns\ form\ at\ point menu-item "Insert ns form at point" clojure-insert-ns-form-at-point) (Insert\ ns\ form\ at\ beginning menu-item "Insert ns form at beginning" clojure-insert-ns-form) (Update\ ns\ form menu-item "Update ns form" clojure-update-ns) (nil menu-item "--") (Version menu-item "Version" clojure-mode-display-version)))) (67108922 . clojure-toggle-keyword-string) keymap (27 keymap (17 . prog-indent-sexp))) ELISP> (define-key clojure-mode-map (kbd "C-c M-j") 'cider-jack-in) *** Eval error *** Key sequence C-c M-j starts with non-prefix key C-c ELISP> *** Welcome to IELM *** Type (describe-mode) for help. ELISP> clojure-mode-map (keymap (3 keymap (27 keymap (99 . cider-connect) ; 关闭desktop-save-mode (106 . cider-jack-in))) (menu-bar keymap (Clojure menu-item "Clojure" (keymap "Clojure" (Toggle\ between\ string\ &\ keyword menu-item "Toggle between string & keyword" clojure-toggle-keyword-string) (Mark\ string menu-item "Mark string" clojure-mark-string) (Insert\ ns\ form\ at\ point menu-item "Insert ns form at point" clojure-insert-ns-form-at-point) (Insert\ ns\ form\ at\ beginning menu-item "Insert ns form at beginning" clojure-insert-ns-form) (Update\ ns\ form menu-item "Update ns form" clojure-update-ns) (nil menu-item "--") (Version menu-item "Version" clojure-mode-display-version)))) (67108922 . clojure-toggle-keyword-string)) ELISP>
eval-after-load add-hook的区别
eval-after-load只会执行一次, 而且时间上会不add-hook要早. 但是在开启desktop-save-mode只后, 可以看到add-hook是先执行了.
猜测, desktop-save-mode开启之后, 重启Emacs的时候, 会出现clojure-mode已经载入, 但是他的eval-after-load却还没有执行的情况. 在正常的情况下不会出现这种情况, 因为eval-after-load中代码是在载入clojure-mode之前执行的. 而且只会执行一次, 也就是说如果clojure-mode已载入, 那么eval-after-load的代码必然已经执行, 而且以后都不再执行.
没有开启desktop-save-mode的情况下, 启动Emacs之后, 执行cider-connect会导致载入clojure-mode, 从而触发eval-after-load, 但是并不会触发clojure-mode hook. 因为还没有buffer使用clojure-mode, REPL用的是cider-repl-mode.