How to define “mode-specific” commands?

elisp

#1

Description

(defun sdcv-forward-dictionary ()
  (interactive)
  ...)

is currently binding to key f in sdcv-mode,But when i run M-x in other major-mode, it also display command name start with sdcv-.

Expect

Hide sdcv-mode commands in other major-mode buffer.

Hypothesis

  1. Remove (interative ...) in all commands inside sdcv-mode.el, but define-key would not work on function.
  2. Define commands only available in sdcv-mode, hidden in other major-mode, not yet this feature.

Relative


#2

Solution

Lambda interactive function :hushed:

(global-set-key (kbd "C-c k") 
  (lambda () (insert "λ"))
;; C-c k is undefined! We tried to bind it to a function

(global-set-key (kbd "C-c m") 
  (lambda () (interactive) (insert "λ"))
;; C-c m is bound to a command that inserts λ

#3

楼上你自问自答真有意思


#4

我一直觉得这是个问题,可以称之为「命令污染」问题,Emacs 命令实在是太多了:

(let ((i 0))
  (mapatoms
   (lambda (symbol)
     (when (commandp symbol)
       (setq i (1+ i)))))
  i)
;; => 7558

而其中有不少是只在特定的 Major Mode 有效、且只适合使用按键调用,比如 Org Mode 的 M-RET (org-meta-return)。或许可以试试实现自己的 M-x,用某种规则过滤掉这些命令。


#5

今天试了一下,可以用make-symbol造出来的符号给lambda命名,这样由于符号本身不在obarray里。所以这个函数也不会显示在M-x的候选列表里

(let ((sym (make-symbol "cm/invisible-function")))
         (defalias sym
           (lambda () (interactive) (message "hi")))
         (global-set-key (kbd "s-i") sym))

#6

这个帖子 1 2 3 楼是怎么回事?


#7
(xref-item-location
 (car (elisp--xref-find-definitions #'org-cycle)))
;; => #s(xref-elisp-location org-cycle nil "~/.local/share/emacs/27.0.50/lisp/org/org.el")

xref 只提供所在文件信息,并不能确定属于哪个 mode,有什么函数可以获得更进一步的信息?