【问题标题】:Org-mode: Filter on tag in agenda view?组织模式:在议程视图中过滤标签?
【发布时间】:2012-04-09 13:34:38
【问题描述】:

议程构建视图时是否可以过滤标签?我已尝试以下方法仅显示与工作相关的约会:

("j" "Jobb"
   ((agenda ""
       ((org-agenda-skip-function '(org-agenda-skip-entry-if 'notregexp":jobb:"))))
    (tags-todo "jobb"))
    ((org-agenda-compact-blocks nil)))

这仅在实际约会被直接标记时有效,但如果约会从父标题继承其标记,则无效:

 * Tider                                                              :jobb:                                                                                                                                                         
 ** Millas arbetstider                                                                                                                                                                                                               
   <2012-04-11 ons 05:00-09:00>                                                                                                                                                                                                     
   <2012-04-12 tor 04:15-08:30>                                                                                                                                                                                                     
   <2012-04-13 fre 14:30-18:30>                           

还有其他方法可以显示继承其标签的约会吗?

【问题讨论】:

  • Jobb 是瑞典人,顺便说一句。

标签: emacs org-mode


【解决方案1】:

问题在于org-agenda-skip-entries-if'notregexp 的交互方式。它将跳过任何与:jobb: 不匹配的条目。即使后面的条目继承了标签,它也没有明确列出,因此它们被跳过。似乎也没有任何内置方法可以匹配(或不匹配)使用org-agenda-skip-entries-if 的标签。如果有这样的功能,它可能是查找标签的更有效方法,但我不知道有这样的功能。

您必须创建一个自定义函数来提供所需的搜索格式。

如果您将议程命令更改为:

("j" "Jobb"
         ((agenda ""
                  ((org-agenda-skip-function '(zin/org-agenda-skip-tag "jobb" 't))))
          (tags-todo "jobb"))
         ((org-agenda-compact-blocks nil)))

并将zin/org-agenda-skip-tag 定义为:

(defun zin/org-agenda-skip-tag (tag &optional others)
  "Skip all entries that correspond to TAG.

If OTHERS is true, skip all entries that do not correspond to TAG."
  (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))
        (current-headline (or (and (org-at-heading-p)
                                   (point))
                              (save-excursion (org-back-to-heading)))))
    (if others
        (if (not (member tag (org-get-tags-at current-headline)))
            next-headline
          nil)
      (if (member tag (org-get-tags-at current-headline))
          next-headline
        nil))))

你会得到我理解的你想要的议程视图。如果我把它倒退了,接下来 3 天的条目不应该出现,你只需要将函数更改为 (zin/org-agenda-skip-tag "jobb")(zin/org-agenda-skip-tag "jobb" 'nil),在这种情况下它们是等效的。

议程视图

在这种情况下,test-new 是我使用的组织文件的名称,可以忽略它。我还将两个标题都设置为TODO,以便在测试功能时让它们可见,因为我将议程限制在一个文件中。

Week-agenda (W15):
Monday      9 April 2012 W15
Tuesday    10 April 2012
Wednesday  11 April 2012
  test-new:    5:00- 9:00 TODO Millas arbetstider                        :jobb::
Thursday   12 April 2012
  test-new:    4:15- 8:30 TODO Millas arbetstider                        :jobb::
Friday     13 April 2012
  test-new:   14:30-18:30 TODO Millas arbetstider                        :jobb::
Saturday   14 April 2012
Sunday     15 April 2012

================================================================================
Headlines with TAGS match: jobb
  test-new:   TODO Tider                                                  :jobb:
  test-new:   TODO Millas arbetstider                                    :jobb::

【讨论】:

  • 这不是我想要的,这不会使该块的议程部分忽略所有未标记为“jobb”的约会
  • 糟糕,我误解了你的问题(回头看很清楚,我只是没有正确阅读)。我将进行编辑以提供一个可以满足您需求的答案(或似乎基于您的示例)。
  • 我从 org-back-to-heading 得到't,所以我不得不用 (save-excursion (progn (org-back-to-heading) (点)))
  • Hrm,只有从标题开始扫描时才会这样做,如果您在任何其他行上,它就会成功。我将编辑代码以包括对这种情况的检查(在这种情况下,只会在标题中出现时间戳)。
  • 这似乎可行,但有没有办法将它与标准 org-agenda-skip-subtree-if 结合起来?
【解决方案2】:

在使用 Jonathan 的回答中的函数几个月来进行这种逐块过滤之后,我发现自己想要能够处理更复杂查询的东西(比如其他块类型使用的匹配字符串),我我想我会把它贴在这里,供以后偶然发现这个问题的人使用。

编辑:my/org-match-at-point-p 的原始实现现在有些过时了。 Org 模式源现在是词法范围的,这改变了org-make-tags-matcher 的合同。过去,todotags-list 变量需要围绕对 org-make-tags-matcher 的调用进行动态范围限定,而现在它们似乎被传递给从调用返回的函数。 (耶!这好多了!)我已经修改了下面的代码以匹配新版本,但我不再使用 Org 模式,所以它只是经过轻微测试。

(defun my/org-match-at-point-p (match)
  "Return non-nil if headline at point matches MATCH.
Here MATCH is a match string of the same format used by
`org-tags-view'."
  (funcall (cdr (org-make-tags-matcher match))
           (org-get-todo-state)
           (org-get-tags-at)
           (org-reduced-level (org-current-level))))

(defun my/org-agenda-skip-without-match (match)
  "Skip current headline unless it matches MATCH.

Return nil if headline containing point matches MATCH (which
should be a match string of the same format used by
`org-tags-view').  If headline does not match, return the
position of the next headline in current buffer.

Intended for use with `org-agenda-skip-function', where this will
skip exactly those headlines that do not match." 
  (save-excursion
    (unless (org-at-heading-p) (org-back-to-heading)) 
    (let ((next-headline (save-excursion
                           (or (outline-next-heading) (point-max)))))
      (if (my/org-match-at-point-p match) nil next-headline))))

如果您仍在使用旧版本的 Org 模式,这里是原始代码。请注意,此版本假定定义 my/org-match-at-point-p 的文件是词法范围的;如果没有,您可以安全地将my/defun-dyn 宏替换为简单的defun

(defmacro my/defun-dyn (&rest def)
  "As `defun', but always in dynamic scope.
A function defined in this way ignores the value of
`lexical-binding' and treats it as if it were nil.

\(fn NAME ARGLIST &optional DOCSTRING DECL &rest BODY)"
  (declare (debug defun)
           (indent defun)
           (doc-string 3))
  `(eval '(defun ,@def) nil))

(my/defun-dyn my/org-match-at-point-p (match &optional todo-only)
  "Return non-nil if headline at point matches MATCH.
Here MATCH is a match string of the same format used by
`org-tags-view'.

If the optional argument TODO-ONLY is non-nil, do not declare a
match unless headline at point is a todo item."
  (let ((todo      (org-get-todo-state))
        (tags-list (org-get-tags-at)))
    (eval (cdr (org-make-tags-matcher match)))))

【讨论】:

  • 我试图理解你的函数my/org-match-at-point,我很难理解todo-only 的来源。查看org-make-tags-matcher 文档,匹配器应该是用三个参数调用,并查看org-tags-matcherthis 实现,它的调用是用todo-only 完成的,而你的不是。我在这里错过了什么?
  • 看来我的代码真的已经过时了。 Org 模式源现在是词法范围的,为了使org-make-tags-matcher 与它一起工作,必须更改匹配器的合同。我会用解释更新答案。
  • 至于todo-only,我记得它曾经是另一个变量,可以在调用周围动态限定范围以改变匹配器的行为(所以我在参数列表中的声明就足够了) , 但这似乎已被删除。我认为匹配字符串语法可能已被增强;手册中提到了我不认识的 ! 运算符。
  • 哦,嘿!太感谢了。这给了我一些我需要在以后追求的指示。
【解决方案3】:

可以通过在议程视图中点击“/”来过滤Agenda Dispatcher

"/" = 在所有议程文件中搜索正则表达式,此外 在 org-agenda-text-search-extra-files 中列出的文件中。这使用 Emacs 命令多次出现。前缀参数可用于 指定每个匹配的上下文行数...

【讨论】:

  • 您能提供更多信息吗?另外,添加适当的标签。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多