From 39a8c36b92a8036562cb170ea0b8be7ba1d2de50 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 18:58:21 -0500 Subject: [PATCH] Add property matcher --- README.org | 7 +++++++ notes.org | 10 ++++++++++ org-agenda-ng.el | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/README.org b/README.org index a1384fd..0fc298e 100644 --- a/README.org +++ b/README.org @@ -66,6 +66,13 @@ Another way to look at it is like a "query language" for Org buffers. For examp (and (not (done)) (tags "Emacs") (priority >= "B")))) ;; => (44154 46469 56008 63965 100008 ...) + + ;; If you kept a database of music in an Org file, you might run a query like this to find tracks + ;; composed by Chopin that do not have their key recorded in the database: + (org-ql "~/org/music.org" + (and (property "genre" "classical") + (property "composer" "Chopin") + (not (property "key")))) #+END_SRC Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. diff --git a/notes.org b/notes.org index 5cfefb4..018ae07 100644 --- a/notes.org +++ b/notes.org @@ -186,6 +186,16 @@ Doesn't seem to make any difference. (regexp "over")) #+END_SRC +** Property matching + +#+BEGIN_SRC elisp + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (property "agenda-group")) + + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (property "agenda-group" "plans")) +#+END_SRC + ** Screenshot code #+BEGIN_SRC elisp diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 54ec866..efd6054 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -128,6 +128,7 @@ NONE-PREDS." (todo #'org-agenda-ng--todo-p) (done #'org-agenda-ng--done-p) (tags #'org-agenda-ng--tags-p) + (property #'org-ql--property-p) (regexp #'org-ql--regexp-p) (org-back-to-heading #'outline-back-to-heading)) (org-with-wide-buffer @@ -474,3 +475,15 @@ comparator, PRIORITY should be a priority string." (save-excursion (goto-char (line-beginning-position)) (re-search-forward regexp end t)))) + +(defun org-ql--property-p (property &optional value) + "Return non-nil if current entry has PROPERTY, and optionally VALUE." + (pcase property + ('nil (user-error "Property matcher requires a PROPERTY argument.")) + (_ (pcase value + ('nil + ;; Check that PROPERTY exists + (org-entry-get (point) property)) + (_ + ;; Check that PROPERTY has VALUE + (string-equal value (org-entry-get (point) property 'selective)))))))