“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。
序言
在上一篇文章的末尾,我说有一个更优雅的办法实现快速设置任务的开始时间,本文便来揭秘这个办法。
Helm
如果说我看得比别人更远些,那是因为我站在巨人的肩膀上。
——牛顿
既要支持预设选项,又要能够方便选择,一个显而易见的办法就是使用下拉列表。要在Emacs中弹出下拉列表,不需要从零开始造轮子,只要基于Helm即可轻松做到。Helm是一个增量补全及选择的框架,利用它的API,可以轻松实现带补全功能的下拉列表,并在选中某一项后执行特定的代码。
这份文档清晰地说明了如何使用Helm的API。在展示具体代码前,先看看成品的效果是怎样的
show the code
Helm的用法朴实无华,只要调用名为helm
的函数即可。helm
有一个叫sources
的重要参数,它接收一个association list,并要求其中有以如下三个符号为car
的cons
:
name
。对应的cdr
部分是下拉列表的名字;candidates
。对应的cdr
部分是下拉列表的所有候选项;action
。对应的cdr
部分是一个函数,代表选中某一项后的处理逻辑。
candidates
可以是一个association list(这也是前述的文档以及我接下来的用法),其中每个cons
的car
部分将作为候选项被展示,cdr
部分则是一个“真实值”(就像是HTML的option标签的文本与它的value
属性间的关系)。Helm贴心地提供了名为helm-marked-candidates
的函数,帮助在这种情况下,获取被选中的候选项对应的cdr
部分的内容。为了利用这个便捷的特性,我将候选项定义为:
1 | (setq *schedule-shortcuts* |
要传给helm
函数的sources
参数的值为:
1 | (defvar *helm-quick-schedule-source* |
有了*helm-quick-schedule-source*
,便可以一窥Helm的风采。按下M-:
并输入(helm :sources *helm-quick-schedule-source*)↵
,会打开一个新的buffer,其中纵向列出了“午餐”、“午休”、“晚餐”,以及“晚上在家”四个选项。可以上下移动,也可以输入目标选项的部分内容,Helm会根据输入过滤候选项。按下回车后,helm
函数返回一个列表,装载着所选中的项对应的cdr
部分——这是因为在*helm-quick-schedule-source*
中action
的部分就是直接返回这个cdr
。
最后,只需将helm
与上一篇文章中定义的lt-next-todo
结合起来即可:
1 | (defun helm-quick-schedule () |
把它绑定到C-c l s
上
1 | (define-key org-mode-map "\C-cls" 'helm-quick-schedule) |
现在,当处于org-mode
模式下的buffer时,只需要按下C-c l s
,便可以轻松选择一个开始时间并在眨眼间设置为光标所在任务的SCHEDULED属性。
后记
Emacs的Helm插件本身已经提供了非常丰富的功能,例如helm-bufferss-list
。我还利用Helm实现查询笔记的入口,待时机成熟了,一定将这方面的心得分享出来。