emui8
1
具体思路:
通过自带的abbrev-mode,在abbrev_defs里面设定四个字符作为严格的缩写词,缩写内容为次常用命令和dired复制的常用目录的绝对路径
"mate" "/home/mate/.emacs.d/"
"test" "eval-defun"
表现行为:
输入缩写词之后,自动用expand-abbrev展开,再调用exit-minibuffer完成
代码如下:
(setq abbrev-mode t)
(setq abbrev-file-name "~/.emacs.d/temp/abbrev_defs"
(defun four-chars ()
(when (and (minibufferp)
(= (length (minibuffer-contents)) 4))
(abbrev-mode 1)
(expand-abbrev)
(exit-minibuffer)))
(defun custom-execute-extended-command ()
(interactive)
(add-hook 'post-command-hook 'four-chars)
(execute-extended-command nil)
(remove-hook 'post-command-hook 'four-chars))
(defun custom-dired-do-copy ()
(interactive)
(add-hook 'post-command-hook 'four-chars)
(dired-do-copy nil)
(remove-hook 'post-command-hook 'four-chars))
存在问题:
- 在上面两个custom-函数执行的时候,不管是不是缩略词,都会在四个字符之后自动执行,我只能尽可能把自己用到的命令和路径都写进去,算是一种掩耳盗铃式的解决方式
- 当使用那些会自动调用minibuffer的命令时候,包括但不限于replace-string,isearch等等,我的解决方案是使用major-mode-map里面绑定的单键快捷键,如果是通过custom-execute-extended-command来调用,就会继承四个字符自动调用的操作,没法用了,不知道怎么解决
- (custom-)dired-do-copy默认执行之后会插入当前路径,但是我缩写词使用的是绝对路径,所以必须把这路径删除
(advice-add 'dired-do-copy :after #'delete-backward-sentence)
这个并没有效果,有人指点我说after之后要加一个定时器,但是我不知道怎么弄,故求助这个,是刚需
我是一个纯菜鸟,这也是一个功能很简单的minibuffer补全,如果有和我类似这样需求的朋友们可以尝试一下,最好emacs -Q来测试
最后就是感谢所有提出建议和解决方案的朋友们,非常感谢大家
yibie
2
(setq abbrev-mode t)
(setq abbrev-file-name "~/.emacs.d/temp/abbrev_defs")
(setq save-abbrevs t)
(defun is-our-abbrev-p (str)
"检查输入的字符串是否是我们定义的缩写词之一"
(and (= (length str) 4) ; 确保长度为4
(assoc str abbrev-table-name-list))) ; 检查是否在缩写表中
;; 改进的 four-chars 函数
(defun four-chars ()
"只在输入的是已定义的缩写词时才展开并退出"
(when (and (minibufferp)
(is-our-abbrev-p (minibuffer-contents)))
(abbrev-mode 1)
(expand-abbrev)
(exit-minibuffer)))
;; 创建一个通用的 minibuffer 包装函数
(defun with-abbrev-completion (orig-fun &rest args)
"为函数添加缩写补全功能的包装器"
(unwind-protect
(progn
(add-hook 'post-command-hook #'four-chars)
(apply orig-fun args))
(remove-hook 'post-command-hook #'four-chars)))
;; 包装 execute-extended-command
(defun custom-execute-extended-command ()
(interactive)
(with-abbrev-completion #'execute-extended-command nil))
;; 包装 dired-do-copy
(defun custom-dired-do-copy ()
(interactive)
(with-abbrev-completion #'dired-do-copy nil))
;; 修复 dired-do-copy 后的路径问题
(defun clear-minibuffer-after-delay ()
"清除 minibuffer 中的内容"
(when (minibufferp)
(delete-region (minibuffer-prompt-end) (point-max))))
(advice-add 'dired-do-copy
:after
(lambda (&rest _)
(run-with-timer 0 nil #'clear-minibuffer-after-delay)))
;; 为特定命令禁用缩写补全
(defvar commands-without-abbrev
'(replace-string isearch-forward isearch-backward)
"不需要缩写补全的命令列表")
(advice-add 'execute-extended-command
:around
(lambda (orig-fun &rest args)
(let ((this-command (car (where-is-internal
(intern (completing-read
"M-x " obarray 'commandp t))
nil t))))
(if (memq this-command commands-without-abbrev)
(apply orig-fun args)
(apply #'with-abbrev-completion orig-fun args)))))
1 个赞
emui8
3
首先非常感谢这位大佬的方案
其次,我刚使用emacs -Q来测试这段代码,只是多了(require 'dired),以便把c和o绑定到两个custom命令上面,同时打开了debug,但是在执行custom-execute-extended-command和custom-dired-do-copy并没有出现预期的结果,还是默认的行为,整个过程也没有报错,不知道为什么
abbrev_defs里面我只写了minibuffer-mode-abbrev-table
是不是我哪里没用对,大佬指点一下