在具有指定标记的条目上对org-after-todo-state-change-hook执行代码

时间:2014-01-22 13:32:50

标签: emacs elisp org-mode

我有一些包含以下内容的组织文件:

* HOLD Some todo heading             :project:
  #+BEGIN_SRC shell
  grunt watch
  #+END_SRC
* TODO Some other heading             :test:
  #+BEGIN_SRC emacs-lisp
  (message "TEST")
  #+END_SRC

我想在时钟输入时从HOLD切换到INPROGRESS状态。这很简单,我明白了。

然后在org-after-todo-state-change-hook上我想执行条目中包含的代码,但仅限于特定的TAGS。

所以,我得到了:

(defun tester/after-change-hook()
  "Test function on hook."
  (when (string= org-state "INPROGRESS") 

    ;; DO SOMETHING on entry with 'project' tag

    ;; DO SOMETHING on entry with 'test' tag

    ;; MAYBE TRY TO EXECUTE CODE ON entry with 'project' tag

    ;; MAYBE TRY TO EXECUTE CODE ON entry with 'test' tag

  )
)
(add-hook 'org-after-todo-state-change-hook 'tester/after-change-hook)

不幸的是,我不知道如何编写函数来执行特定标记上的代码或在特定标记上执行内联代码。

我一直在尝试使用org-scan-tags函数或org-element-map

我可以看到other people can make use of them

但不幸的是,所有这些Lisp的东西对我来说就像是一个黑魔法。 我不知道如何编写将在当前时钟任务上测试标签的功能。 有人可以用这个lisp语法帮我吗? 从理论上讲,我知道做我想做的事情需要哪些功能。 在现实生活中,我不知道如何在lisp中写这个。

1 个答案:

答案 0 :(得分:0)

匹配标记列表中成员的一种方法是使用类似(member "test" tags)的内容 - 请参阅下面的示例,其中名为test的标记的存在将产生祝贺消息,或者去如果名为test的标记不存在,则显示-fish消息。您还可以使用正则表达式来匹配整个单词或单词的一部分,但这超出了本示例的范围。


以下是测试以下示例的4步方法。 [该示例由@lawlist使用Org版本8.2.5c进行测试。]

  • (1)将我的整个代码复制并粘贴到您的.emacs文件中;保存文件;并重新启动Emacs。

  • (2)打开新缓冲区并输入:

    * This is a task. :test:lawlist:
    
  • (3) M-x org-mode

  • (4)将光标放在您刚输入的行上的任意位置:M-x example

一旦你启动并运行了这个例子(没有进行任何修改),那么你可以慢慢地进行自己的修改 - 在整个过程的不同阶段继续测试你的新代码,这样任何你编码中的错误转动不会太过失控(这会使调试变得更加困难)。


(require 'org)

(require 'org-element)

(defun example ()
(interactive)
  (save-excursion
    (org-back-to-heading t)
    (let* (
        (element (org-element-at-point))
        (title (org-element-property :title element))
        (tags (org-element-property :tags element)))
      (cond
        ((and
            (equal title "")
            (not (equal tags nil)))
          (error "The `title` cannot be blank."))
        ((and
            (equal tags nil)
            (not (equal title "")))
          (error "The `tags` cannot be blank."))
        ((and
            (equal title "")
            (equal tags nil))
          (error "The `title` and `tags` cannot be blank."))
        ((and
            (not (equal tags nil))
            (not (equal title "")))
          (message "TITLE:  %s  |  TAG(S):  %s" title tags)
          (if (member "test" tags)
            (message "Congratulations:  You found a match.")
            (message "Uh-oh -- no match -- go fish!")))  ))))