Emacs: 智能感知和操作光标处的语法对象

我在 2008 年开发了 thing-edit.el , 虽然这个插件平常没啥存在感, 但是几乎是天天都在用的插件.

thing-edit.el 简单来说, 就是不用移动光标, 会自动把光标处的各种语法对象 (表达式、邮件地址、文件名、URL、单词、符号、函数定义、列表、句子、空格、段落、行、注释、括号内容等)进行识别并操作, 比如复制, 剪切或者粘贴 kill-ring 内容.

thing-edit.el 相对于其他复制插件的优势在于你完全不用移动光标即可智能的感知语法对象并进行快速的操作. 等操作完成以后可以继续从当前的位置继续编程.

安装方法

  1. 下载 thing-edit git 里面的 thing-edit.el 放到 ~/elisp 目录
  2. 把下面的配置加入到 ~/.emacs 中
(add-to-list 'load-path (expand-file-name "~/elisp"))
(require 'thing-edit)

使用方法

可以把你喜欢的按键绑定下面的命令:

命令 解释
thing-cut-sexp cut sexp around cursor.
thing-copy-sexp copy sexp around cursor.
thing-replace-sexp replace sexp around cursor with content of kill-ring.
thing-cut-email cut email string around cursor
thing-copy-email copy email string around cursor.
thing-replace-email replace email string around cursor with content of kill-ring.
thing-cut-filename cut filename string around cursor.
thing-copy-filename copy filename string around cursor.
thing-replace-filename replace filename string around cursor with content of kill-ring.
thing-cut-url cut url string around cursor.
thing-copy-url copy url string around cursor.
thing-replace-url replace url string around cursor with content of kill-ring.
thing-cut-word cut word string around cursor.
thing-copy-word copy word string around cursor.
thing-replace-word replace word string around cursor with content of kill-ring.
thing-cut-symbol cut symbol string around cursor.
thing-copy-symbol copy symbol string around cursor.
thing-replace-symbol replace symbol string around cursor with content of kill-ring.
thing-cut-defun cut function string around cursor.
thing-copy-defun copy function string around cursor.
thing-replace-defun replace function string around cursor with content of kill-ring.
thing-cut-list cut list string around cursor.
thing-copy-list copy list string around cursor.
thing-replace-list replace list string around cursor with content of kill-ring.
thing-cut-sentence cut sentence string around cursor.
thing-copy-sentence copy sentence string around cursor.
thing-replace-sentence replace sentence string around cursor with content of kill-ring.
thing-cut-whitespace cut whitespace string around cursor.
thing-copy-whitespace copy whitespace string around cursor.
thing-replace-whitespace replace whitespace string around cursor with content of kill-ring.
thing-cut-page cut page string around cursor.
thing-copy-page copy page string around cursor.
thing-replace-page replace page string around cursor with content of kill-ring.
thing-cut-line cut current line.
thing-copy-line copy current line.
thing-replace-line replace current line with content of kill-ring.
thing-cut-to-line-end cut string to end of line.
thing-copy-to-line-end copy string to end of line.
thing-replace-to-line-end replace string to end of line with content of kill-ring.
thing-cut-to-line-beginning cut string to beginning of line.
thing-copy-to-line-beginning copy string to beginning of line.
thing-replace-to-line-beginning replace string to beginning of line with content of kill-ring.
thing-cut-comment cut comment.
thing-copy-comment copy comment.
thing-replace-comment replace comment with content of kill-ring.
thing-cut-paragrap cut paragraph around cursor.
thing-copy-paragrap copy paragraph around cursor.
thing-replace-paragrap replace paragraph around cursor with content of kill-ring.
thing-cut-parentheses cut parentheses around cursor.
thing-copy-parentheses copy parentheses around cursor.
thing-replace-parentheses replace parentheses around cursor with content of kill-ring.

期待发PR

thing-edito.el 本来放到我自己的 插件目录中

如果各位喜欢, 觉得有新的功能需要扩展, 我会把我自己的插件从 lazycat-emacs 中抽取出来, 单独成一个 git 仓库方便大家发送PR.

谢谢 谢鹏 同学编写的 thing-replace-* 函数, 非常的好用.

9赞

🥶我是来吐槽命名的。。

刚开始看的文档的时候除了copy以外的都没看懂是干嘛的。。 thing-paste-X看起来是把东西放到kill-ring里,一般这种操作不是叫kill吗。。然后thing-replace-X看起来像 yank。。然后 sexp的文档又写着正则表达式。。

kill 不一定可以复制的出来.

paste 更像剪切的意思, kill 以后可以继续拷贝到别处

replace 是把当前的语法对象用 kill-ring 的对象替换掉, 如果 yank 你首先要选中再粘贴.

kill 不一定可以复制的出来.

为啥。。

paste 更像剪切的意思, kill 以后可以继续拷贝到别处

即使是剪切。。一般都叫 cutpaste是粘贴。。虽然我还是倾向copykillyank

嗯, paste 确实搞错了, 十年前的英语, 没有检查, 我一会改一下.

试用了一下,感觉挺方便的。如果thing-copy-url能识别[[link][descrition]]格式的链接就更好了。

欢迎发补丁.

有推荐的快捷键配置吗?

我用我自己的one-key.el

https://github.com/manateelazycat/lazycat-emacs/blob/575e12e3b63524335ebb997e82bc8ec09abfe383/site-lisp/config/init-thing-edit.el#L93 这是我自己的 one-key.el 按键配置

https://github.com/manateelazycat/thing-edit/commit/89922e6e89ee36b85f59b81a2c81e4c6511d7695 加了一个拷贝时提醒范围的功能:

1赞

我试用的时候,调用copy命令没问题,调用replace 和cut 命令时报下面的错误呢 Wrong type argument: commandp, thing-replace-word Wrong type argument: commandp, thing-cut-list

(require 'thing-edit)了吗?

require了,copy命令是可以的

问题找到了,是因为有旧版本的thing-edit.el文件导致的。

1赞

感觉可以搞个 hydra 来集成。不过功能与 expand-region 很类似。

我用one-key.el

这个感觉和expand-region做一样的事情

我是自己定义的map

(defvar peng-thing-edit-map (make-sparse-keymap)
  "Keybinding for `thing-edit'")

;; Copy.
(define-key peng-thing-edit-map (kbd "w") 'thing-copy-word)
(define-key peng-thing-edit-map (kbd "s") 'thing-copy-symbol)
(define-key peng-thing-edit-map (kbd "m") 'thing-copy-email)
(define-key peng-thing-edit-map (kbd "f") 'thing-copy-filename)
(define-key peng-thing-edit-map (kbd "u") 'thing-copy-url)
(define-key peng-thing-edit-map (kbd "x") 'thing-copy-sexp)
(define-key peng-thing-edit-map (kbd "t") 'thing-copy-page)
(define-key peng-thing-edit-map (kbd "v") 'thing-copy-sentence)
(define-key peng-thing-edit-map (kbd "g") 'thing-copy-block)
(define-key peng-thing-edit-map (kbd "o") 'thing-copy-whitespace)
(define-key peng-thing-edit-map (kbd "i") 'thing-copy-list)
(define-key peng-thing-edit-map (kbd "c") 'thing-copy-comment)
(define-key peng-thing-edit-map (kbd "h") 'thing-copy-defun)
(define-key peng-thing-edit-map (kbd "p") 'thing-copy-parentheses)
(define-key peng-thing-edit-map (kbd "a") 'thing-copy-to-line-beginning)
(define-key peng-thing-edit-map (kbd "e") 'thing-copy-to-line-end)

;; Cut.
(define-key peng-thing-edit-map (kbd "SPC w") 'thing-cut-word)
(define-key peng-thing-edit-map (kbd "SPC s") 'thing-cut-symbol)
(define-key peng-thing-edit-map (kbd "SPC m") 'thing-cut-email)
(define-key peng-thing-edit-map (kbd "SPC f") 'thing-cut-filename)
(define-key peng-thing-edit-map (kbd "SPC u") 'thing-cut-url)
(define-key peng-thing-edit-map (kbd "SPC x") 'thing-cut-sexp)
(define-key peng-thing-edit-map (kbd "SPC t") 'thing-cut-page)
(define-key peng-thing-edit-map (kbd "SPC v") 'thing-cut-sentence)
(define-key peng-thing-edit-map (kbd "SPC g") 'thing-cut-block)
(define-key peng-thing-edit-map (kbd "SPC o") 'thing-cut-whitespace)
(define-key peng-thing-edit-map (kbd "SPC i") 'thing-cut-list)
(define-key peng-thing-edit-map (kbd "SPC c") 'thing-cut-comment)
(define-key peng-thing-edit-map (kbd "SPC h") 'thing-cut-defun)
(define-key peng-thing-edit-map (kbd "SPC p") 'thing-cut-parentheses)
(define-key peng-thing-edit-map (kbd "SPC a") 'thing-cut-to-line-beginning)
(define-key peng-thing-edit-map (kbd "SPC e") 'thing-cut-to-line-end)

;; Replace
(define-key peng-thing-edit-map (kbd "W") 'thing-replace-word)
(define-key peng-thing-edit-map (kbd "S") 'thing-replace-symbol)
(define-key peng-thing-edit-map (kbd "M") 'thing-replace-email)
(define-key peng-thing-edit-map (kbd "F") 'thing-replace-filename)
(define-key peng-thing-edit-map (kbd "U") 'thing-replace-url)
(define-key peng-thing-edit-map (kbd "X") 'thing-replace-sexp)
(define-key peng-thing-edit-map (kbd "T") 'thing-replace-page)
(define-key peng-thing-edit-map (kbd "V") 'thing-replace-sentence)
(define-key peng-thing-edit-map (kbd "G") 'thing-replace-block)
(define-key peng-thing-edit-map (kbd "O") 'thing-replace-whitespace)
(define-key peng-thing-edit-map (kbd "I") 'thing-replace-list)
(define-key peng-thing-edit-map (kbd "C") 'thing-replace-comment)
(define-key peng-thing-edit-map (kbd "H") 'thing-replace-defun)
(define-key peng-thing-edit-map (kbd "P") 'thing-replace-parentheses)

(define-key peng-thing-edit-map (kbd "A") 'thing-paste-to-line-beginning)
(define-key peng-thing-edit-map (kbd "E") 'thing-paste-to-line-end)

;; add two key to select
(define-key peng-thing-edit-map (kbd "l") 'peng-select-to-line-end)
(define-key peng-thing-edit-map (kbd "j") 'peng-select-to-line-beginning)
(define-key peng-thing-edit-map (kbd ";") 'peng-select-list)

然后再把这个map绑一个你自己喜欢的key就可以了:

(global-set-key (kbd "your-keys") peng-thing-edit-map)

看起来不错,先试试看