首页
归档
友情链接
关于
Search
1
在wsl2中安装archlinux
293 阅读
2
从零开始配置 vim(15)——状态栏配置
171 阅读
3
nvim番外之将配置的插件管理器更新为lazy
160 阅读
4
2018总结与2019规划
149 阅读
5
PDF标准详解(五)——图形状态
126 阅读
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
登录
Search
标签搜索
c++
c
学习笔记
emacs
elisp
windows
文本操作术
编辑器
NeoVim
Vim
win32
读书笔记
VimScript
linux
文本编辑器
投资理财
Java
反汇编
OLEDB
数据库编程
Masimaro
累计撰写
447
篇文章
累计收到
33
条评论
首页
栏目
软件与环境配置
读书笔记
编程
Thinking
FIRE
菜谱
翻译
页面
归档
友情链接
关于
搜索到
2
篇与
的结果
2026-09-02
《elisp 每日一练》——minibuffer输入读取和set-transient-map 临时热键状态机
我们在前面介绍了 completing-read 给用户提供选项,让用户输入,但是如何处理这种需要用户主动输入的情况呢?本节我们将介绍一些主动读取用户输入的接口,然后补充一个我们在前面练习中涉及到的函数 set-transient-map背景知识completing-read 主要是提供几个候选项供用户选择,有点类似一般GUI程序的下拉列表框。而我们今天介绍的 read-from-minibuffer 就像GUI程序中的文本框。它的函数签名如下:(read-from-minibuffer PROMPT &optional INITIAL-CONTENTS KEYMAP READ HIST DEFAULT-VALUE)其中常用参数的含义如下:PROMPT 提示词INITIAL-CONTENTS 预先填写的内容,后续可以修改READ 如果为 t,会自动调用 Lisp Reader,将输入的文本直接解析为 Lisp 对象DEFAULT-VALUE 当用户直接按回车时返回的字符串该接口相对来说是一个偏底层的接口,如果程序预先指定用户输入数据的类型,可以选择一些相对上层的封装函数:read-string 读取纯文本read-number 读取数字read-command 读取一个命令read-file-name 读取一个文件名read-directory-name 读取一个目录名称我们可以通过 read 作为前缀搜索类似的函数。另外一个今天要补充的函数就是 set-transient-map(set-transient-map KEYMAP &optional KEEP-PRED ON-EXIT)它会临时将对应的keymap挂起,在下一次按键之后,会调用 KEEP-PRED 参数绑定的函数返回值决定是否卸载keymap。它的函数返回值有三种情况:nil 执行一个命令后理解卸载,也就是一次性的t 保持,直到下一次调用时该函数返回nil数字 如果是数字值,保持激活状态,直到连续执行了指定次数的命令后自动卸载练习今天我们的练习,我们来实现一个快速的文本大小写与替换功能。它的功能如下:利用region 选中一段文本按 C-c t 进入该模式,此时我们利用 set-tranient-map 挂载一个快捷键的keymap按 u 将选中文本转为大写按 l 转为小写按 c 转为首字母大写(Captial)按 r 调用 read-string 读取你要替换的字符串,然后替换选中区域按 q 或任意其他键退出我们先定义这些功能的函数(defun my/upcase-region() "选中区域的文本转化为大写" (interactive) (when (use-region-p) (upcase-region (region-beginning) (region-end)))) (defun my/downcase-region() "选中区域文本转为小写" (interactive) (when (use-region-p) (downcase-region (region-beginning) (region-end)))) (defun my/capitalize-region() "选中区域首字母大写" (interactive) (when (use-region-p) (capitalize-region (region-beginning) (region-end)))) (defun my/replace-region() "替换选中区域的文本" (interactive) (when (use-region-p) (let* ((old-text (buffer-substring (region-beginning) (region-end))) (new-text (read-string (format "替换 '%s' 为:" old-text)))) (delete-region (region-beginning) (rregion-end)) (insert new-text))))然后我们可以定义一个keymap,将这些操作进行绑定(defvar my/text-operator-transient-map (let ((map (make-sparse-keymap))) (keymap-set map "u" #'my/upcase-region) (keymap-set map "l" #'my/downcase-region) (keymap-set map "c" #'my/capitalize-region) (keymap-set map "r" #'my/replace-region) (keymap-set map "q" (lambda() (interactive) (set-transient-map nil))) map))最后我们绑定一个快捷键进入该模式(defun my/start-text-operate() (interactive) (if (use-region-p) (set-transient-map my/text-operator-transient-map) (message "请先选中一段文本"))) (keymap-global-set "C-c t" #'my/start-text-operate)小结本篇我们介绍了如何读取minibuffer 中用户的输入,以及补充了一个关于快捷键绑定的额外函数。本节涉及到的函数有:read-from-minibuffer 以及基于该函数实现的read 系列函数set-transient-map
2026年09月02日
7 阅读
0 评论
0 点赞
2026-08-25
《elisp 每日一练》—— 前缀按键
上一节我们提到Emacs中keymap上某个键可以绑定一个具体的函数,也可以绑定另一个keymap,如果绑定另一个keymap,它就变成了一个前缀键,本篇我们来讨论前缀和自建keymap背景知识(defun my/hello() (interactive) (message "hello world")) (keymap-local-set "C-c p h" 'my/hello)我们先从上面的例子开始。上面我们通过 keymap-local-set 在当前buffer中绑定了一个快捷键。根据之前介绍的查找顺序,它在当前buffer的局部keymap中找到了这个绑定。而我们将它拆解开来,实际上它先找到 C-c ,发现它绑定了一个 keymap 实际上 C-c 就是一个前缀。然后在它绑定的 keymap 中找到了关于 p 的内容,p也绑定了一个 keymap,接着在这个 keymap 中找到了 h 绑定的函数,最终执行这个函数。我们可以用这个图来描述这个树形结构C-c ↓ keymap ↓ p ↓ keymap ↓ h → my/hello也就是说我们调用 keymap-local-set 绑定快捷键时,Emacs已经帮我们构建了这样一个多层的keymap 结构。只不过这个过程我们之前没注意到。既然Emacs已经默默帮我们构造了这样一个keymap,为什么还要提供让我们手动构造自己keymap的方式呢?因为这样可以使前缀的 keymap 成为一个独立的、可复用、可管理的对象,方便插件的开发者组织自己的快捷键。例如 Projectile 有一组 C-c p 的快捷键,那么我们就可以创建一个keymap,将它绑定到 C-c p 的位置,然后我们只要操作这个 keymap ,就可以做到自然的将这些操作都绑定到 C-c p 下面创建一个 keymap 可以使用 make-sparse-keymap。后续我们可以将它创建的 keymap 放入到 define-key 或者 keymap-set 函数的 keymap 参数中。当然你也可以使用 define-prefix-command 这个宏来定义一个专门用于前缀的 keymap 。这个函数会将创建的keymap 映射为一个函数,后续我们可以调用该函数获得底层的 keymap。练习本节我们利用这两种机制来创建一个类似 Projectile 插件的一组以 C-c p 开头的函数。我们绑定这么几个函数:C-c p f 绑定到 find-fileC-c p b 绑定到 switch-bufferC-c p g s 绑定到 vc-dirC-c p g l 绑定到 vc-print-log(defvar my/git-sub-map (make-sparse-keymap) "用于二级git菜单的keymap") (define-prefix-command 'my/project-sparse-map) ;; 绑定一级菜单 (keymap-set my/project-sparse-map "f" #'find-file) (keymap-set my/project-sparse-map "b" #'switch-buffer) ;; 绑定二级 (keymap-set my/git-sub-map "s" #'vc-dir) (keymap-set my/git-sub-map "l" #'vc-print-log) ;; 将二级map绑定到一级map (keymap-set my/project-sparse-map "g" my/git-sub-map) ;; 绑定一级菜单 (global-set-key (kbd "C-c p") my/project-sparse-map) (message "my/project-sparse-map 内部结构: %S" my/project-sparse-map)小结本节我们简单了解了一下前缀和嵌套keymap的内容,一般来讲,创建一个keymap可以使用下面两个函数make-sparse-keymapdefine-prefix-command
2026年08月25日
7 阅读
0 评论
0 点赞