写了个小函数提示今天要做的任务

假设了当emacs打开的时候,emacs-server也同样打开

    (defun colawithsauce/org-agenda-get-todos ()
      "Get todo and scheduled items until today."
      (let ((matched-items '())
            (print-result ""))
        (dolist (match
                 (org-map-entries 'org-heading-components "SCHEDULED<=\"<today>\"/-DONE" 'agenda))
          (when (member (nth 2 match) '("[!]" "TODO" "[?]" "HACKING"))
            (push (concat "■ " (nth 4 match)) matched-items)))
        (while matched-items
          (setq print-result (concat (car matched-items) "\n" print-result))
          (setq matched-items (cdr matched-items)))
        (message print-result)))

然后再在 ~/.zshrc 最前面加一句

if [ "$(pgrep emacs)" ]
then
    echo "今天要做的任务:"
    echo "$(emacsclient --eval '(colawithsauce/org-agenda-get-todos)'|tr -d \")"
fi

效果如下:

2 个赞

改进了一下shell里面的函数

task_today="$(pgrep emacs > /dev/null && emacsclient --eval '(colawithsauce/org-agenda-get-todos)'| sed 's/^\"//;s/\"$//')"
if [ "$(pgrep emacs)" ] && [ ${task_today} ];
then
    echo "今天的安排:"
    echo ${task_today}
fi

一直想要实现这样的功能,太好啦。不过我主要在window10里面用emacs,可以实现吗?

将这段文本插入到你的scratch或者dashboard都可以的吧

每次打开shell都要卡一下,好不爽,改成写进一个文件里面,然后每次 todo 的状态改变了就覆写这个文件,然后在shell里面读。

这样做还有一个好处就是emacs daemon没有必要开着也可以显示今天要做的任务了。

(with-eval-after-load 'org
  ;; Task reminding
  (defun colawithsauce/org-agenda-get-todos ()
    "Get todo and scheduled items until today."
    (let ((matched-items '())
          (print-result ""))
      (dolist (match
               (org-map-entries 'org-heading-components "SCHEDULED<=\"<today>\"/-DONE" 'agenda))
        (when (member (nth 2 match) '("[!]" "TODO" "[?]" "HACKING"))
          (push (concat "■ " (nth 4 match)) matched-items)))
      (while matched-items
        (setq print-result (concat (car matched-items) "\n" print-result))
        (setq matched-items (cdr matched-items)))
      (message print-result)))
  (defun colawithsauce/org-agenda-write-file ()
    "Write todo and scheduled items list to FILENAME."
    (with-temp-buffer
      (insert (colawithsauce/org-agenda-get-todos))
      (write-file "~/.task_today")))
  (add-hook 'org-after-todo-state-change-hook 'colawithsauce/org-agenda-write-file)
)

在shell里面

task_today="$(cat ~/.task_today)"
if [ ${task_today} ];
then
    echo "今天的安排:"
    echo ${task_today}
fi

又写了一个将今天的任务写在scratch buffer的小函数,下面是我现在的全部配置:

(with-eval-after-load 'org
  ;; Task reminding
  (defun colawithsauce/org-agenda-get-todos ()
    "Get todo and scheduled items until today."
    (let ((matched-items '())
          (print-result ""))
      (dolist (match
               (org-map-entries 'org-heading-components "SCHEDULED<=\"<today>\"/-DONE" 'agenda))
        (when (member (nth 2 match) '("[!]" "TODO" "[?]" "HACKING"))
          (push (concat "■ " (nth 4 match)) matched-items)))
      (while matched-items
        (setq print-result (concat (car matched-items) "\n" print-result))
        (setq matched-items (cdr matched-items)))
      (message print-result)))
  (defun colawithsauce/org-agenda-write-file ()
    "Write todo and scheduled items list to FILENAME."
    (with-temp-buffer
      (insert (colawithsauce/org-agenda-get-todos))
      (write-file "~/.task_today")))
  (defun colawithsauce/org-agenda-write-scratch-buffer ()
    "Write todo and scheduled item list to scratch buffer after-init."
    (with-current-buffer "*scratch*"
      (let* ((todo-list (butlast (split-string (colawithsauce/org-agenda-get-todos) "\n")))
             (todo-count (length todo-list)))
        (insert
         (format "%s\n" (make-string 70 ?\;))
         (format ";; Hey! ♥%s♥!\n;; There are ♥%d♥ tasks today :-D\n" (user-login-name) todo-count))
        (while todo-list
          (insert (format ";;   %s\n" (car todo-list)))
          (setq todo-list (cdr todo-list)))
        (insert (format "%s\n" (make-string 70 ?\;)))
        (end-of-buffer))))

  (add-hook 'org-after-todo-state-change-hook 'colawithsauce/org-agenda-write-file)
  (add-hook 'after-init-hook 'colawithsauce/org-agenda-write-scratch-buffer)

)

可能出现的问题:有的人的org-mode是延迟加载的,新加的这个函数假定了 org-mode 在开启emacs 的时候就加载了,而没有延迟加载。

补图

研究了几天终于把函数大致弄明白了,但在win10下的spacemacs一直没成功试出效果。现在的问题是要实现提示当日todo起码要先设定org文件吧?另外org文件里面楼主您的todo文件是什么样子的呢?比如有的todo没有设置schedule,有的设置了优先级[a]什么的,如果todo文件格式不一样的话,代码中的匹配项也应该要改变吧?

嗯,我的需求就是显示scheduled的未完成任务就好了。过期的没有完成的任务和今天要做的任务。比如今天我的emacs如此提示我:

image

我的org文件如下

注意的是,这些文件都是在agenda里面的

再次更新,这次更新了每次更改的时候都会重新写入 scratch 的功能

(with-eval-after-load 'org-agenda
  ;; Task reminding
  (defun colawithsauce/org-agenda-get-todos ()
    "Get todo and scheduled items until today."
    (let ((matched-items '())
          (print-result ""))
      (dolist (match
               (org-map-entries 'org-heading-components "SCHEDULED<=\"<today>\"/-DONE" 'agenda))
        (when (member (nth 2 match) '("[!]" "TODO" "[?]" "HACKING"))
          (push (concat "■ " (nth 4 match)) matched-items)))
      (while matched-items
        (setq print-result (concat (car matched-items) "\n" print-result))
        (setq matched-items (cdr matched-items)))
      (message print-result)))
  (defun colawithsauce/org-agenda-write-file (&optional arg)
    "Write todo and scheduled items list to file. And write
to scratch buffer."
    ;; Write in file
    (with-temp-buffer
      (insert (colawithsauce/org-agenda-get-todos))
      (write-file "~/.task_today"))
    ;; Write in scratch buffer
    (with-current-buffer "*scratch*"
      (erase-buffer)
      (let* ((todo-list (butlast (split-string (colawithsauce/org-agenda-get-todos) "\n")))
             (todo-count (length todo-list)))
        (insert
         (format "%s\n" (make-string 70 ?\;))
         (format ";; Hey! ♥%s♥ !\n;; There are %d tasks for you to do now !!!\n" (user-login-name) todo-count))
        (while todo-list
          (insert (format ";;   %s\n" (car todo-list)))
          (setq todo-list (cdr todo-list)))
        (insert (format "%s\n" (make-string 70 ?\;)))
        (end-of-buffer))))

  (add-hook 'org-after-todo-state-change-hook 'colawithsauce/org-agenda-write-file)
  (add-hook 'after-init-hook 'colawithsauce/org-agenda-write-file)
  (add-hook 'after-make-frame-functions 'colawithsauce/org-agenda-write-file))

主要做了两个改动

  1. 将写入 ~/.task_today 文件与写入 *scratch* 合并成了同一个函数

  2. 改动了 hook 使之更加符合我的需要:

    1. 每次改变 todo 状态之后,重新写入 .task_today 与 scratch,这已经可以应付大多数情况。
    2. 每次启动的时候检查(因为我会在安卓上面使用 orgzly 来管理任务,所以会有不经过 org-after-todo-state-change-hook 的任务 todo 状态改变的情况,因此需要加这条,如果不用,可以不加这条,以加快启动速度。
    3. 每次创建新的frame的时候检查(这是因为我用的是 daemon 模式启动的,因此好像有的时候2会不启作用?我记得有过这样的情况,但是我已经不想花时间去检查了(真是怠惰呢)。因为加上这一句也没有啥大不了的,因为如果agenda-files 是全部打开的的话,这个函数的执行速度是非常快的,没有什么影响)

org-agenda有内置的功能吧,输出成pdf,html,txt都可以的。

配合org-agenda-custom-commands,可以设置输出agenda还是list还是自定义函数、限制org-agenda-files的范围、tags的筛选等等。

啊这,我又重复造轮子了 :cry: 就当练习写elisp好了 :joy:

嗯,没关系啊,对比一下Org里的实现也是很好的学习过程吧,也许之后看到有什么gap的地方可以提交patch呢

1 个赞