乍听之下,不无道理;仔细揣摩,胡说八道

0%

快速设置任务的开始时间(下)

“实战Elisp”系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。

序言

上一篇文章的末尾,我说有一个更优雅的办法实现快速设置任务的开始时间,本文便来揭秘这个办法。

Helm

如果说我看得比别人更远些,那是因为我站在巨人的肩膀上。
——牛顿

既要支持预设选项,又要能够方便选择,一个显而易见的办法就是使用下拉列表。要在Emacs中弹出下拉列表,不需要从零开始造轮子,只要基于Helm即可轻松做到。Helm是一个增量补全及选择的框架,利用它的API,可以轻松实现带补全功能的下拉列表,并在选中某一项后执行特定的代码。

这份文档清晰地说明了如何使用Helm的API。在展示具体代码前,先看看成品的效果是怎样的

show the code

Helm的用法朴实无华,只要调用名为helm的函数即可。helm有一个叫sources的重要参数,它接收一个association list,并要求其中有以如下三个符号为carcons

  1. name。对应的cdr部分是下拉列表的名字;
  2. candidates。对应的cdr部分是下拉列表的所有候选项;
  3. action。对应的cdr部分是一个函数,代表选中某一项后的处理逻辑。

candidates可以是一个association list(这也是前述的文档以及我接下来的用法),其中每个conscar部分将作为候选项被展示,cdr部分则是一个“真实值”(就像是HTML的option标签的文本与它的value属性间的关系)。Helm贴心地提供了名为helm-marked-candidates的函数,帮助在这种情况下,获取被选中的候选项对应的cdr部分的内容。为了利用这个便捷的特性,我将候选项定义为:

1
2
3
4
5
(setq *schedule-shortcuts*
'(("午餐" . (12 0))
("午休" . (13 0))
("晚餐" . (18 35))
("晚上在家" . (22 5))))

要传给helm函数的sources参数的值为:

1
2
3
4
5
(defvar *helm-quick-schedule-source*
`((name . "设置TODO的SCHEDULED属性")
(candidates . *schedule-shortcuts*)
(action . (lambda (candidate)
(helm-marked-candidates)))))

有了*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
2
3
4
5
6
(defun helm-quick-schedule ()
"从下拉列表选择完后SCHEDULED模式后修改当前TODO条目的SCHEDULED属性。"
(interactive)
(let ((spec (car (helm :sources '(*helm-quick-schedule-source*)))))
(when spec
(apply 'lt-next-todo spec))))

把它绑定到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实现查询笔记的入口,待时机成熟了,一定将这方面的心得分享出来。

Liutos wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
你的一点心意,我的十分动力。