本文是“实战Elisp”系列的第一篇。本系列旨在讲述我使用Elisp定制Emacs的经验,抛砖引玉,还请广大Emacs同好不吝赐教——如果真的有广大Emacs用户的话,哈哈哈。
序言
用Emacs的org-mode安排业余时间颇有些时日,渐渐地开始编写一些Elisp函数来改善自己的使用体验。
日程管理中一个常见的需求,便是给任务设定一个开始时间。在org-mode中,这可以调用函数org-schedule实现:将光标移动到一个任务上,再按下C-c C-s,会出现一个日历界面,帮助选择日期和时间来作为日程的开始时间。具体效果如下图所示
<video id="video" controls="" preload="none">
<source id="mp4" src="https://raw.githubusercontent.com/Liutos/riverbed/master/pictures/20200109/org-mode设定任务开始时间.mp4" type="video/mp4">
</video>
久而久之发现,设置的开始时间不外乎是中午12点、下午1点、晚上10点等。这是因为业余时间是相对固定的,比如午饭、午休,以及晚上在家洗完澡等。有规律便有优化的空间。既然每次输入的内容都一样,干脆预设几个开始时间,直接选择即可。
平凡的实现
一个朴素的想法,是为这些固定的时间点各自编写一个Elisp函数,并绑定到不同的快捷键上,每次设置开始时间时就按下对应的快捷键。循着这个思路,我定义了如下的Elisp函数:
(defun lt-lunch-todo ()
"将开始时间设置为中午12点"
(lt-next-todo 12 0))
(defun lt-rest-todo ()
"将开始时间设置为下午1点"
(lt-next-todo 13 0))
(defun lt-supper-todo ()
"将开始时间设置为傍晚6点35分"
(lt-next-todo 18 40))
(defun lt-night-todo ()
"将开始时间设置为晚上10点"
(lt-next-todo 21 30))
lt-next-todo的定义如下
(defun lt-next-todo (hour minute)
"设置光标所在行为一个TODO条目,并设置其SCHEDULED为HOUR:MINUTE。
如果当前的时间已经晚于HOUR:MINUTE,那么将会设定为明天的目标小时。"
(cl-assert (integerp hour))
(cl-assert (integerp minute))
(org-todo "TODO")
(org-set-tags nil t)
(let ((current-hour (string-to-number (format-time-string "%H")))
scheduled)
(cond ((> current-hour hour)
(setf scheduled (format "+1d %02d:%02d" hour minute)))
(t (setf scheduled (format "%02d:%02d" hour minute))))
(message "scheduled: %s" scheduled)
(org-schedule nil scheduled)))
除了绑定不同快捷键,也可以直接调用:将光标移动到任务标题上,按下M-:,输入lt-lunch-todo,最后按下回车。鉴于每次都按这么多键实在是太麻烦,我又编写了四个AppleScript脚本代劳键盘操作,再用BetterTouchTools定制了四个Touchbar按钮,以便一键调用这四个AppleScript脚本。举个例子,负责调用lt-lunch-todo的AppleScript脚本的内容为
tell application "Emacs"
activate
end tell
tell application "System Events"
keystroke ":" using {option down}
keystroke "(lt-lunch-todo)"
keystroke return
end tell
BetterTouchTools中的按钮的设置如下图所示
后记
这套方法用久后发现缺陷蛮多:
- 要定义很多高度雷同的Elisp函数;
- 要编写很多高度雷同的AppleScript脚本;
- 要定制很多高度雷同的BetterTouchTools按钮;
高度雷同、高度雷同、高度雷同,重要的事情说三遍。有规律便有优化的空间,于是我换了一种更好的方式,实现了可扩展的、优雅的快速设置任务开始时间的办法。
欲知后事如何,且听下回分解。
如果你希望观看排版效果更好的版本(比如视频可以成功嵌入),可以阅读原文。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。