From 2a5ec2e4fdc662921f0c7a2e8b877620da3bb5ca Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 10:12:13 -0500 Subject: [PATCH 001/560] Meta: 0.4-pre --- README.org | 4 ++++ org-ql.el | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 3ac0cf5..73cb982 100644 --- a/README.org +++ b/README.org @@ -363,6 +363,10 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4-pre + +Nothing new yet. + ** 0.3 *Added* diff --git a/org-ql.el b/org-ql.el index e90dd8a..eb2cc78 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.3 +;; Version: 0.4-pre ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda From 51ab6401b2f9f6cb193dc3ee89fa6a5430441ced Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 10:12:20 -0500 Subject: [PATCH 002/560] Docs: (--def-plain-query-fn) Fix docstring --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index eb2cc78..13dde58 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1274,7 +1274,7 @@ A and B are Org headline elements." ;; ends up being not defined correctly at expansion time. (defmacro org-ql--def-plain-query-fn () - "Define function `org-ql--input-query'. + "Define function `org-ql--plain-query'. Builds the PEG expression using predicates defined in `org-ql-predicates' and `org-ql-predicates-extra-aliases'." (let* ((predicates (--map (symbol-name (plist-get it :name)) From acf8e0e0fb7ec5d5ed729430fe642c4077fd9bd6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 11:16:08 -0500 Subject: [PATCH 003/560] Notes: Add idea --- notes.org | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/notes.org b/notes.org index 344b550..77cd1c2 100644 --- a/notes.org +++ b/notes.org @@ -2,6 +2,39 @@ * Tasks +** TODO [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + ** TODO [#A] Document sorters Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. @@ -195,6 +228,9 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or #+END_SRC ** TODO [#A] Outline path in buffers-files arg +:PROPERTIES: +:ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 +:END: e.g. From 7e11145badf0964f7d520548242088df74f03884 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 12:37:34 -0500 Subject: [PATCH 004/560] Fix: (--defpred) Debug declaration To work with preds with aliases. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 13dde58..084138f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -124,7 +124,7 @@ docstring. BODY is the body of the predicate. Predicates will be called with point on the beginning of an Org heading and should return non-nil if the heading's entry is a match." - (declare (debug (symbolp listp stringp def-body)) + (declare (debug ([&or symbolp listp] listp stringp def-body)) (indent defun)) (let* ((aliases (when (listp name) (cdr name))) From 8d680a8e797c2ddef26a12623defad3a13a8eb88 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 12:39:26 -0500 Subject: [PATCH 005/560] Add: node-value-cache, --value-at Not used for anything in this comment, but will be in the outline-path predicates. Also should probably use it for the tags cache. --- README.org | 3 ++- org-ql.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 73cb982..f72bb43 100644 --- a/README.org +++ b/README.org @@ -365,7 +365,8 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre -Nothing new yet. +*Internal* ++ Added generic node data cache to speed up recursive, tree-based queries. ** 0.3 diff --git a/org-ql.el b/org-ql.el index 084138f..dfc48db 100644 --- a/org-ql.el +++ b/org-ql.el @@ -100,6 +100,13 @@ tick, and another hash table keyed on buffer position, whose values are a list of two lists, inherited tags and local tags, as strings.") +(defvar org-ql-node-value-cache (make-hash-table :weakness 'key) + "Per-buffer node cache. +Keyed by buffer. Each value is a cons of the buffer's modified +tick, and another hash table keyed on buffer position, whose +values are alists in which the key is a function and the value is +the value returned by it at that node.") + (defvar org-ql-predicates (list (list :name 'org-back-to-heading :fn (symbol-function 'org-back-to-heading))) "Plist of predicates, their corresponding functions, and their docstrings. @@ -419,6 +426,45 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." org-ql-tags-cache)) (puthash position all-tags tags-cache)))) +;; TODO: Use --value-at for tags cache. + +(defun org-ql--value-at (position fn) + "Return FN's value at POSITION in current buffer. +Values compared with `equal'." + ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables + ;; bound in the else clause, so destructured variables that are non-nil, + ;; like found caches, are not available in the else clause. + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-node-value-cache)) + (modified-tick (car buffer-cache)) + (position-cache (cdr buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (value-cache (gethash position position-cache)) + (cached-value (alist-get fn value-cache nil nil #'equal))) + ;; Found in cache: return it. + (pcase cached-value + ('org-ql-nil nil) + (_ cached-value)) + ;; Not found in cache: get value and cache it. + (let ((new-value (or (funcall fn) 'org-ql-nil))) + ;; Check caches again, because it may have been set now, e.g. by + ;; recursively going up an outline tree. + ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? + (setf buffer-cache (gethash (current-buffer) org-ql-node-value-cache) + modified-tick (car buffer-cache) + position-cache (cdr buffer-cache) + value-cache (when position-cache + (gethash position position-cache)) + buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (unless (and buffer-cache buffer-unmodified-p) + ;; Buffer-local node cache empty or invalid: make new one. + (setf position-cache (make-hash-table)) + (puthash (current-buffer) + (cons (buffer-modified-tick) position-cache) + org-ql-node-value-cache)) + (map-put value-cache fn new-value) + (puthash position value-cache position-cache) + new-value))) + (defun org-ql--add-markers (element) "Return ELEMENT with Org marker text properties added. ELEMENT should be an Org element like that returned by From c06e5518eb830b2cc079bc61fc9ba32549710103 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 12:41:23 -0500 Subject: [PATCH 006/560] Add: Predicates outline-path, outline-path-segment --- README.org | 7 +++++ org-ql.el | 70 ++++++++++++++++++++++++++++++++++++++++++++ tests/test-org-ql.el | 19 ++++++++++++ 3 files changed, 96 insertions(+) diff --git a/README.org b/README.org index f72bb43..574e056 100644 --- a/README.org +++ b/README.org @@ -178,6 +178,10 @@ Arguments are listed next to predicate names, where applicable. + ~habit~ :: Return non-nil if entry is a habit. + ~heading (&rest regexps)~ :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). + ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. ++ =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of =STRINGS=. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~. + - Aliases: =olp=. ++ =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches =STRINGS=. Matches =STRINGS= as a contiguous segment of the outline path. Each string is compared as a substring. For example the path =Food/Fruits/Grapes= would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~. + - Aliases: =olps=. + =path (&rest regexps)= :: Return non-nil if current heading's buffer's filename path matches any of =REGEXPS= (regexp strings). Without arguments, return non-nil if buffer is file-backed. + ~priority (&optional comparator-or-priority priority)~ :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. + ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. @@ -365,6 +369,9 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre +*Added* ++ Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql.el b/org-ql.el index dfc48db..65f1ff9 100644 --- a/org-ql.el +++ b/org-ql.el @@ -426,6 +426,18 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." org-ql-tags-cache)) (puthash position all-tags tags-cache)))) +(defun org-ql--outline-path () + "Return outline path for heading at point." + (save-excursion + (let ((heading (nth 4 (org-heading-components)))) + (if (org-up-heading-safe) + ;; MAYBE: It seems wrong to call the cache function from + ;; inside this function, like a violation of separation of + ;; concern. Can this be rewritten to not work that way? + (append (org-ql--value-at (point) #'org-ql--outline-path) + (list heading)) + (list heading))))) + ;; TODO: Use --value-at for tags cache. (defun org-ql--value-at (position fn) @@ -556,6 +568,14 @@ Replaces bare strings with (regexp) selectors, and appropriate (ts-apply :hour 23 :minute 59 :second 59)))) `(,pred :to ,to))) + ;; Outline paths. + (`(,(or 'outline-path 'olp) . ,strings) + ;; Regexp quote headings. + `(outline-path ,@(mapcar #'regexp-quote strings))) + (`(,(or 'outline-path-segment 'olps) . ,strings) + ;; Regexp quote headings. + `(outline-path-segment ,@(mapcar #'regexp-quote strings))) + ;; Priorities (`(priority ,(and (or '= '< '> '<= '>=) comparator) ,letter) ;; Quote comparator. @@ -922,6 +942,44 @@ Tests both inherited and local tags." (when (tags-p local) (seq-intersection tags local)))))))) +;; MAYBE: Preambles for outline-path predicates. Not sure if possible without complicated logic. + +(org-ql--defpred (outline-path olp) (&rest regexps) + "Return non-nil if current node's outline path matches all of REGEXPS. +Each string is compared as a regexp to each element of the node's +outline path with `string-match'. For example, if an entry's +outline path were \"Food/Fruits/Grapes\", it would match any of +the following queries: + + (olp \"Food\") + (olp \"Fruits\") + (olp \"Food\" \"Fruits\") + (olp \"Fruits\" \"Grapes\") + (olp \"Food\" \"Grapes\")" + (let ((entry-olp (org-ql--value-at (point) #'org-ql--outline-path))) + (cl-loop for h in regexps + always (cl-member h entry-olp :test #'string-match)))) + +(org-ql--defpred (outline-path-segment olps) (&rest regexps) + "Return non-nil if current node's outline path matches segment REGEXPS. +Matches REGEXPS as a contiguous segment of the outline path. +Each regexp is compared to each element of the node's outline +path with `string-match'. For example, if an entry's outline +path were \"Food/Fruits/Grapes\", it would match any of the +following queries: + + (olp \"Food\") + (olp \"Fruit\") + (olp \"Food\" \"Fruit\") + (olp \"Fruit\" \"Grape\") + +But it would not match the following, because they do not match a +contiguous segment of the outline path: + + (olp \"Food\" \"Grape\")" + ;; MAYBE: Allow anchored matching. + (org-ql--infix-p regexps (org-ql--value-at (point) #'org-ql--outline-path))) + (org-ql--defpred (tags-inherited tags-i itags) (&rest tags) "Return non-nil if current heading's inherited tags include one or more of TAGS (a list of strings). If TAGS is nil, return non-nil if heading has any inherited tags." @@ -1302,6 +1360,18 @@ A and B are Org headline elements." (a-priority t) (b-priority nil))))) +(defun org-ql--infix-p (infix list) + "Return non-nil if INFIX is an infix of LIST. +Each element of INFIX is compared using `string-match', so each +element should be a regexp string." + (cl-loop with infix-length = (length infix) + while (and list + (>= (length list) infix-length)) + thereis (cl-loop for i in infix + for l in list + always (string-match i l)) + do (pop list))) + ;;;;; Plain query parsing ;; This section implements parsing of "plain," non-Lisp queries using the `peg' diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index c7b95bc..66c3053 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -479,6 +479,25 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((heading "Take over" "world")) '("Take over the world")))) + (describe "(outline-path)" + (org-ql-it "with one argument" + (org-ql-expect ((outline-path "symphony")) + '("Write a symphony"))) + (org-ql-it "with two arguments" + (org-ql-expect ((outline-path "idea" "symphony")) + '("Write a symphony")))) + + (describe "(outline-path-segment)" + (org-ql-it "with one argument" + (org-ql-expect ((outline-path-segment "symphony")) + '("Write a symphony"))) + (org-ql-it "with a contiguous segment" + (org-ql-expect ((outline-path-segment "idea" "symphony")) + '("Write a symphony"))) + (org-ql-it "with a non-contiguous segment" + (org-ql-expect ((outline-path-segment "data" "symphony")) + nil))) + (describe "(path)" (org-ql-it "without arguments" (org-ql-expect ((path)) From ad20029721954472c69a334f26f57c20e8f4067d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 13:11:37 -0500 Subject: [PATCH 007/560] Notes: Update --- notes.org | 150 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 77 insertions(+), 73 deletions(-) diff --git a/notes.org b/notes.org index 77cd1c2..a52cf2b 100644 --- a/notes.org +++ b/notes.org @@ -2,47 +2,10 @@ * Tasks -** TODO [#A] Outline path predicate - -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: - -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - ** TODO [#A] Document sorters Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - ** TODO [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. @@ -162,6 +125,41 @@ Well, a bit of fiddling (lots of trial-and-error required) produced this: That seems pretty usable! +** TODO [#A] Outline path in buffers-files arg +:PROPERTIES: +:ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 +:END: + +e.g. + +#+BEGIN_SRC elisp + (org-ql (olp "~/org/inbox.org" "Emacs" "Ideas") + (todo "NEXT")) +#+END_SRC + +Also, should support an ~id~ one. + +** TODO [#A] Tools for saving queries and accessing them [2/4] + ++ Added example to =examples.org=. + +*** DONE Save query from ql-agenda buffer + +*** DONE Access saved query from saved query list + +*** TODO Org link types +:PROPERTIES: +:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e +:END: + +This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. + +**** TODO For all parameters + +**** TODO For saved queries + +*** TODO Bookmarks + ** TODO [#B] Timeline view e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: @@ -227,41 +225,6 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or (org-ql-agenda--agenda nil nil :strings strings))) #+END_SRC -** TODO [#A] Outline path in buffers-files arg -:PROPERTIES: -:ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 -:END: - -e.g. - -#+BEGIN_SRC elisp - (org-ql (olp "~/org/inbox.org" "Emacs" "Ideas") - (todo "NEXT")) -#+END_SRC - -Also, should support an ~id~ one. - -** TODO [#A] Tools for saving queries and accessing them [2/4] - -+ Added example to =examples.org=. - -*** DONE Save query from ql-agenda buffer - -*** DONE Access saved query from saved query list - -*** TODO Org link types -:PROPERTIES: -:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e -:END: - -This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. - -**** TODO For all parameters - -**** TODO For saved queries - -*** TODO Bookmarks - ** TODO [#B] Add more sorters? + [ ] =category= @@ -439,6 +402,10 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or e.g. doesn't currently show the =View= header. +** TODO [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + ** TODO [#C] ~org-agenda-skip-function~ As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: @@ -488,6 +455,41 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary +** UNDERWAY [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. + ** UNDERWAY [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. @@ -531,7 +533,7 @@ Items would be structs, and the =group-by= argument would be a list of accessors Not sure if it should automatically add the number of items to the header, or if that should be done manually. -** MAYBE [#C] "Node" caching +** UNDERWAY [#B] "Node" caching [2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. @@ -539,6 +541,8 @@ It would probably be an all-encompassing system, because predicates would need t Maybe a good improvement to make later, after the project is more developed. +[2019-10-07 Mon 13:08] This has basically been implemented in =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but as functions and values rather than with structs. It remains to be seen how this works with =ancestor= queries, but I suspect it will help a lot. + *** Struct PoC code This works okay (except the priority accessor needs to be fixed, because Org priorities are awkward to get). I'm guessing all the extra function calls would make it undesirable in cases of returning many results, but it's a flexible concept that makes sorting easy. From 34cdbd5c87e0bd6ae8d3a72ac3473456dcc9e4af Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 15:35:31 -0500 Subject: [PATCH 008/560] Docs: Add info manual Updating readme accordingly, based on org-super-agenda's, which is based on Magit's and Org's. --- README.org | 113 +++--- org-ql.info | 978 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1048 insertions(+), 43 deletions(-) create mode 100644 org-ql.info diff --git a/README.org b/README.org index 574e056..a7258dc 100644 --- a/README.org +++ b/README.org @@ -1,10 +1,10 @@ #+TITLE: org-ql -#+BEGIN_HTML - -#+END_HTML +# NOTE: Using =BEGIN_HTML= for this causes TeX/info export to fail, but this HTML block works. +#+HTML: -[[https://melpa.org/#/org-ql][file:https://melpa.org/packages/org-ql-badge.svg]] [[https://stable.melpa.org/#/org-ql][file:https://stable.melpa.org/packages/org-ql-badge.svg]] +# NOTE: To avoid having this in the info manual, we use HTML rather than Org syntax; it still appears with the GitHub renderer. +#+HTML: This package provides a query language for Org files. It offers two syntax styles: Lisp-like sexps and search engine-like keywords. @@ -63,12 +63,12 @@ These commands and functions are included: + *Showing an agenda-like view:* - ~org-ql-search~ (command) - ~org-ql-view~ (command) - - =org-ql-view-sidebar= (command) + - ~org-ql-view-sidebar~ (command) - ~org-ql-block~ (agenda block function) + *Showing a tree in a buffer:* - - =org-ql-sparse-tree= (command) + - ~org-ql-sparse-tree~ (command) + *Showing results with Helm*: - - =helm-org-ql= (command) + - ~helm-org-ql~ (command) + *Returning a list of matches or acting on them:* - ~org-ql~ (macro) - ~org-ql-select~ (function) @@ -76,6 +76,7 @@ These commands and functions are included: Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. +# TODO: Find a way to get these examples included in the info manual. Lisp code examples are in [[examples.org]]. ** Commands @@ -129,7 +130,9 @@ Show a sidebar window listing views stored in =org-ql-views= for easy access. I Show items in ~FILES~ from last ~DAYS~ days with timestamps of ~TYPE~. ~TYPE~ may be ~ts~, ~ts-active~, ~ts-inactive~, ~clocked~, ~closed~, ~deadline~, ~planning~, or ~scheduled~. =FILES= defaults to those returned by the function =org-agenda-files=. -*** org-ql-sparse-tree =(query &key keep-previous (buffer (current-buffer)))= +*** org-ql-sparse-tree + +Arguments: ~(query &key keep-previous (buffer (current-buffer)))~ Show a sparse tree for ~QUERY~ in ~BUFFER~ and return number of results. The tree will show the lines where the query matches, and any other context defined in ~org-show-context-detail~, which see. @@ -171,29 +174,29 @@ Note that the =priority= predicate does not support comparators in the non-sexp Arguments are listed next to predicate names, where applicable. -+ ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). -+ ~children (&optional query)~ :: Return non-nil if current heading has direct child headings. If ~QUERY~, test it against child headings. This selector may be nested, e.g. to match grandchild headings. -+ ~descendants (&optional query)~ :: Return non-nil if current heading has descendant headings. If ~QUERY~, test it against descendant headings. This selector may be nested (if you can grok the nesting!). -+ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. -+ ~habit~ :: Return non-nil if entry is a habit. -+ ~heading (&rest regexps)~ :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). -+ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. -+ =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of =STRINGS=. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~. - - Aliases: =olp=. -+ =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches =STRINGS=. Matches =STRINGS= as a contiguous segment of the outline path. Each string is compared as a substring. For example the path =Food/Fruits/Grapes= would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~. - - Aliases: =olps=. -+ =path (&rest regexps)= :: Return non-nil if current heading's buffer's filename path matches any of =REGEXPS= (regexp strings). Without arguments, return non-nil if buffer is file-backed. -+ ~priority (&optional comparator-or-priority priority)~ :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. -+ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. -+ ~regexp (&rest regexps)~ :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. -+ ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. -+ =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of =TAGS= (a list of strings). If TAGS is nil, return non-nil if heading has any inherited tags. - - Aliases: =inherited-tags=, =tags-i=, =itags=. -+ =tags-local (&optional tags)= :: Return non-nil if current heading's local tags include one or more of =TAGS= (a list of strings). If TAGS is nil, return non-nil if heading has any local tags. - - Aliases: =local-tags=, =tags-l=, =ltags=. -+ =tags-all (tags)= :: Return non-nil if current heading includes all of =TAGS=. Tests both inherited and local tags. - - Aliases: =tags&=. -+ ~todo (&optional keywords)~ :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). ++ =category (&optional categories)= :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). ++ =children (&optional query)= :: Return non-nil if current heading has direct child headings. If ~QUERY~, test it against child headings. This selector may be nested, e.g. to match grandchild headings. ++ =descendants (&optional query)= :: Return non-nil if current heading has descendant headings. If ~QUERY~, test it against descendant headings. This selector may be nested (if you can grok the nesting!). ++ =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. ++ =habit= :: Return non-nil if entry is a habit. ++ =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). ++ =level (level-or-comparator &optional level)= :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. ++ =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of ~STRINGS~. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~. + - Aliases: ~olp~. ++ =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches ~STRINGS~. Matches ~STRINGS~ as a contiguous segment of the outline path. Each string is compared as a substring. For example the path ~Food/Fruits/Grapes~ would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~. + - Aliases: ~olps~. ++ =path (&rest regexps)= :: Return non-nil if current heading's buffer's filename path matches any of ~REGEXPS~ (regexp strings). Without arguments, return non-nil if buffer is file-backed. ++ =priority (&optional comparator-or-priority priority)= :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. ++ =property (property &optional value)= :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. ++ =regexp (&rest regexps)= :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. ++ =tags (&optional tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. ++ =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags. + - Aliases: ~inherited-tags~, ~tags-i~, ~itags~. ++ =tags-local (&optional tags)= :: Return non-nil if current heading's local tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any local tags. + - Aliases: ~local-tags~, ~tags-l~, ~ltags~. ++ =tags-all (tags)= :: Return non-nil if current heading includes all of ~TAGS~. Tests both inherited and local tags. + - Aliases: ~tags&~. ++ =todo (&optional keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). *** Date/time predicates :PROPERTIES: @@ -208,21 +211,21 @@ All of these predicates take optional keyword arguments ~:from~, ~:to:~, and ~:o Argument values should be either a number of days (positive to look forward, or negative to look backward), a ~ts~ struct, or a string parseable by ~parse-time-string~ (the string may omit the time value). -*Predicates:* -+ ~ts~ :: Return non-nil if current entry has a timestamp in given period. If no arguments are specified, return non-nil if entry has any timestamp. -+ ~ts-active~, ~ts-a~ :: Like ~ts~, but only matches active timestamps. -+ ~ts-inactive~, ~ts-i~ :: Like ~ts~, but only matches inactive timestamps. ++ *Predicates* + - =ts= :: Return non-nil if current entry has a timestamp in given period. If no arguments are specified, return non-nil if entry has any timestamp. + - =ts-active=, =ts-a= :: Like =ts=, but only matches active timestamps. + - =ts-inactive=, =ts-i= :: Like =ts=, but only matches inactive timestamps. The following predicates, in addition to the keyword arguments, can also take a single argument, a number, which looks backward or forward a number of days. The number can be negative to invert the direction. -*Backward-looking:* -+ ~clocked~ :: Return non-nil if current entry was clocked in given period. If no arguments are specified, return non-nil if entry was clocked at any time. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. -+ ~closed~ :: Return non-nil if current entry was closed in given period. If no arguments are specified, return non-nil if entry was closed at any time. ++ *Backward-looking* + - =clocked= :: Return non-nil if current entry was clocked in given period. If no arguments are specified, return non-nil if entry was clocked at any time. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + - =closed= :: Return non-nil if current entry was closed in given period. If no arguments are specified, return non-nil if entry was closed at any time. -*Forward-looking:* -+ ~deadline~ :: Return non-nil if current entry has deadline in given period. If argument is =auto=, return non-nil if entry has deadline within =org-deadline-warning-days=. If no arguments are specified, return non-nil if entry has any deadline. -+ ~planning~ :: Return non-nil if current entry has planning timestamp in given period (i.e. its deadline, scheduled, or closed timestamp). If no arguments are specified, return non-nil if entry is scheduled at any time. -+ ~scheduled~ :: Return non-nil if current entry is scheduled in given period. If no arguments are specified, return non-nil if entry is scheduled at any time. ++ *Forward-looking* + - =deadline= :: Return non-nil if current entry has deadline in given period. If argument is =auto=, return non-nil if entry has deadline within =org-deadline-warning-days=. If no arguments are specified, return non-nil if entry has any deadline. + - =planning= :: Return non-nil if current entry has planning timestamp in given period (i.e. its deadline, scheduled, or closed timestamp). If no arguments are specified, return non-nil if entry is scheduled at any time. + - =scheduled= :: Return non-nil if current entry is scheduled in given period. If no arguments are specified, return non-nil if entry is scheduled at any time. ** Functions / Macros :PROPERTIES: @@ -371,6 +374,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Added* + Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). ++ Info manual. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. @@ -571,9 +575,32 @@ Generates the predicate subtree. If ~org-ql~ is loaded byte-compiled, the argument lists are not named properly (not sure why, as ~help-function-arglist~ is supposed to handle that). We could run the function in another Emacs process with ~async~ to avoid this. +* COMMENT Export setup :noexport: +:PROPERTIES: +:TOC: ignore +:END: + +# Copied from org-super-agenda's readme, in which much was borrowed from Org's =org-manual.org=. + +#+OPTIONS: broken-links:t *:t + +** Info export options + +#+TEXINFO_DIR_CATEGORY: Emacs +#+TEXINFO_DIR_TITLE: Org QL: (org-ql) +#+TEXINFO_DIR_DESC: Query language, search commands, and saved views for Org files + +# NOTE: We could use these, but that causes a pointless error, "org-compile-file: File "..README.info" wasn't produced...", so we just rename the files in the after-save-hook instead. +# #+TEXINFO_FILENAME: org-ql.info +# #+EXPORT_FILE_NAME: org-ql.texi + ** File-local variables +# NOTE: Setting org-comment-string buffer-locally is a nasty hack to work around GitHub's org-ruby's HTML rendering, which does not respect noexport tags. The only way to hide this tree from its output is to use the COMMENT keyword, but that prevents Org from processing the export options declared in it. So since these file-local variables don't affect org-ruby, wet set org-comment-string to an unused keyword, which prevents Org from deleting this tree from the export buffer, which allows it to find the export options in it. And since org-export does respect the noexport tag, the tree is excluded from the info page. + # Local Variables: -# eval: (require 'org-make-toc) # before-save-hook: org-make-toc +# after-save-hook: (lambda nil (when (and (require 'ox-texinfo nil t) (org-texinfo-export-to-info)) (delete-file "README.texi") (rename-file "README.info" "org-ql.info" t))) +# org-export-initial-scope: buffer +# org-comment-string: "NOTCOMMENT" # End: diff --git a/org-ql.info b/org-ql.info new file mode 100644 index 0000000..f585e33 --- /dev/null +++ b/org-ql.info @@ -0,0 +1,978 @@ +This is README.info, produced by makeinfo version 5.2 from README.texi. + +INFO-DIR-SECTION Emacs +START-INFO-DIR-ENTRY +* Org QL: (org-ql). Query language, search commands, and saved views for Org files. +END-INFO-DIR-ENTRY + + +File: README.info, Node: Top, Next: Contents, Up: (dir) + +org-ql +****** + +* Menu: + +* Contents:: +* Screenshots:: +* Installation:: +* Usage:: +* Changelog:: +* Notes:: +* License:: + +— The Detailed Node Listing — + + + +Installation + +* Quelpa:: + + +Usage + +* Commands:: +* Queries:: +* Functions / Macros:: + +Commands + +* org-ql-search:: +* helm-org-ql:: +* org-ql-view:: +* org-ql-view-sidebar:: +* org-ql-view-recent-items:: +* org-ql-sparse-tree:: + + + +Queries + +* Non-sexp query syntax:: +* Predicates:: +* Date/time predicates:: + + + +Functions / Macros + +* Agenda-like views:: +* Listing / acting-on results:: + +Changelog + +* 0.4-pre: 04-pre. +* 0.3: 03. +* 0.2.3: 023. +* 0.2.2: 022. +* 0.2.1: 021. +* 0.2: 02. +* 0.1: 01. + + + +Notes + +* Comparison with Org Agenda searches:: +* org-sidebar:: + +This package provides a query language for Org files. It offers two +syntax styles: Lisp-like sexps and search engine-like keywords. + + It includes three libraries: The org-ql library is flexible and may +be used as a backend for other tools. The libraries org-ql-search and +helm-org-ql provide interactive search commands and saved views. + + +File: README.info, Node: Contents, Next: Screenshots, Prev: Top, Up: Top + +1 Contents +********** + + • • • + • • • • • + +File: README.info, Node: Screenshots, Next: Installation, Prev: Contents, Up: Top + +2 Screenshots +************* + + +File: README.info, Node: Installation, Next: Usage, Prev: Screenshots, Up: Top + +3 Installation +************** + +The package may be installed directly from MELPA +(https://melpa.org/#/org-ql) or with other tools like Quelpa +(https://framagit.org/steckerhalter/quelpa). + + After installation, you can use the commands without additional +configuration. _Note: The command helm-org-ql only works if the package +helm-org is installed; Helm is not a dependency of this package, so it’s +not automatically installed._ + + To use the functions and macros in your own Elisp code, use libraries +org-ql and org-ql-view. + +* Menu: + +* Quelpa:: + + +File: README.info, Node: Quelpa, Up: Installation + +3.1 Quelpa +========== + +Installing with Quelpa (https://framagit.org/steckerhalter/quelpa) is +easy: + + 1. Install quelpa-use-package + (https://framagit.org/steckerhalter/quelpa-use-package#installation) + (which can be installed directly from MELPA). + 2. Add this form to your init file: + + (use-package org-ql + :quelpa (org-ql :fetcher github :repo "alphapapa/org-ql")) + + +File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top + +4 Usage +******* + +These commands and functions are included: + + • *Showing an agenda-like view:* + • ‘org-ql-search’ (command) + • ‘org-ql-view’ (command) + • ‘org-ql-view-sidebar’ (command) + • ‘org-ql-block’ (agenda block function) + • *Showing a tree in a buffer:* + • ‘org-ql-sparse-tree’ (command) + • *Showing results with Helm*: + • ‘helm-org-ql’ (command) + • *Returning a list of matches or acting on them:* + • ‘org-ql’ (macro) + • ‘org-ql-select’ (function) + • ‘org-ql-query’ (function) + + Feedback on these APIs is welcome. Eventually, after being tested +and polished, they will be considered stable. + + Lisp code examples are in . + +* Menu: + +* Commands:: +* Queries:: +* Functions / Macros:: + + +File: README.info, Node: Commands, Next: Queries, Up: Usage + +4.1 Commands +============ + +* Menu: + +* org-ql-search:: +* helm-org-ql:: +* org-ql-view:: +* org-ql-view-sidebar:: +* org-ql-view-recent-items:: +* org-ql-sparse-tree:: + + +File: README.info, Node: org-ql-search, Next: helm-org-ql, Up: Commands + +4.1.1 org-ql-search +------------------- + +_Note: This command supports both sexp queries and ._ + + Read ‘QUERY’ and search with ‘org-ql’. Interactively, prompt for +these variables: + + ‘BUFFERS-FILES’: ‘A’ list of buffers and/or files to search. +Interactively, may also be: + + • ‘buffer’: search the current buffer + • ‘all’: search all Org buffers + • ‘agenda’: search buffers returned by the function + ‘org-agenda-files’ + • An expression which evaluates to a list of files/buffers + • A space-separated list of file or buffer names + + ‘GROUPS’: An ‘org-super-agenda’ group set. See variable +‘org-super-agenda-groups’. + + ‘NARROW’: When non-nil, don’t widen buffers before searching. +Interactively, with prefix, leave narrowed. + + ‘SORT’: One or a list of ‘org-ql’ sorting functions, like ‘date’ or +‘priority’. + + *Bindings:* Keys bound in results buffer. + • g: Refresh results. + • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with + command ‘org-ql-view’). + + *Note:* The view buffer is currently put in ‘org-agenda-mode’, which +means that _some_ Org Agenda commands work, such as jumping to entries +and changing item priorities (without necessarily updating the view). +This feature is experimental and not guaranteed to work correctly with +all commands. (It works to the extent it does because the appropriate +text properties are placed on each item, imitating an Agenda buffer.) + + +File: README.info, Node: helm-org-ql, Next: org-ql-view, Prev: org-ql-search, Up: Commands + +4.1.2 helm-org-ql +----------------- + +_Note: This command uses ._ + + This command displays matches with Helm. *Note:* Helm is not a +package dependency, so this command only works if the package helm-org +is installed. + + • Press C-x C-s in the Helm session to save the results to an + org-ql-search buffer. + + +File: README.info, Node: org-ql-view, Next: org-ql-view-sidebar, Prev: helm-org-ql, Up: Commands + +4.1.3 org-ql-view +----------------- + +Choose and display a view stored in ‘org-ql-views’. + + +File: README.info, Node: org-ql-view-sidebar, Next: org-ql-view-recent-items, Prev: org-ql-view, Up: Commands + +4.1.4 org-ql-view-sidebar +------------------------- + +Show a sidebar window listing views stored in org-ql-views for easy +access. In the sidebar, press RET or mouse-1 to show the view at point, +and press c to customize the view at point. + + +File: README.info, Node: org-ql-view-recent-items, Next: org-ql-sparse-tree, Prev: org-ql-view-sidebar, Up: Commands + +4.1.5 org-ql-view-recent-items +------------------------------ + +Show items in ‘FILES’ from last ‘DAYS’ days with timestamps of ‘TYPE’. +‘TYPE’ may be ‘ts’, ‘ts-active’, ‘ts-inactive’, ‘clocked’, ‘closed’, +‘deadline’, ‘planning’, or ‘scheduled’. FILES defaults to those +returned by the function org-agenda-files. + + +File: README.info, Node: org-ql-sparse-tree, Prev: org-ql-view-recent-items, Up: Commands + +4.1.6 org-ql-sparse-tree +------------------------ + +Arguments: ‘(query &key keep-previous (buffer (current-buffer)))’ + + Show a sparse tree for ‘QUERY’ in ‘BUFFER’ and return number of +results. The tree will show the lines where the query matches, and any +other context defined in ‘org-show-context-detail’, which see. + + ‘QUERY’ is an ‘org-ql’ query sexp (quoted, since this is a function). +‘BUFFER’ defaults to the current buffer. When ‘KEEP-PREVIOUS’ is +non-nil (interactively, with prefix), the outline is not reset to the +overview state before finding matches, which allows stacking calls to +this command. Runs ‘org-occur-hook’ after making the sparse tree. + + +File: README.info, Node: Queries, Next: Functions / Macros, Prev: Commands, Up: Usage + +4.2 Queries +=========== + +An org-ql query is a lisp form which may contain arbitrary lisp forms, +as well as certain built-in predicates. It is byte-compiled into a +predicate function which is tested with point on each heading in an Org +buffer; when it returns non-nil, the heading matches the query. + + *Notes:* + • Bare strings like ‘"string"’ are automatically converted to + ‘(regexp "string")’ predicates. + • Standard numeric comparator function symbols (‘<’, ‘<=’, ‘>’, ‘>=’, + ‘=’ ) need not be quoted when passed as an argument to predicates + which accept them. The resemblance to infix notation is + coincidental. + +* Menu: + +* Non-sexp query syntax:: +* Predicates:: +* Date/time predicates:: + + +File: README.info, Node: Non-sexp query syntax, Next: Predicates, Up: Queries + +4.2.1 Non-sexp query syntax +--------------------------- + +The command org-ql-search also accepts, and the command helm-org-ql only +accepts, an alternative, non-sexp query syntax. The syntax is simple, +and a few examples of queries in both syntaxes should suffice. By +default, when multiple predicates are used, they are combined with +boolean and. + +Sexp syntax Non-sexp syntax +------------------------------------------------------------------------------------------------ +‘(todo)’ ‘todo:’ +‘(todo "SOMEDAY")’ ‘todo:SOMEDAY’ +‘(todo "SOMEDAY" "WAITING")’ ‘todo:SOMEDAY,WAITING’ +‘(ts :on today)’ ‘ts:on=today’ +‘(ts-active :from "2017-01-01" :to "2018-01-01")’ ‘ts-active:from=2017-01-01,to=2018-01-01’ +‘(clocked :on -1)’ ‘clocked:on=-1’ +‘(heading "quoted phrase" "word")’ ‘heading:"quoted phrase",word’ +‘(and (tags "book" "books") (priority "A"))’ ‘tags:book,books priority:A’ +‘(priority >= B)’ ‘priority:A,B’ + + Note that the priority predicate does not support comparators in the +non-sexp syntax, so multiple priorities should be passed instead, as +seen in the last example. + + +File: README.info, Node: Predicates, Next: Date/time predicates, Prev: Non-sexp query syntax, Up: Queries + +4.2.2 Predicates +---------------- + +Arguments are listed next to predicate names, where applicable. + +‘category (&optional categories)’ + Return non-nil if current heading is in one or more of ‘CATEGORIES’ + (a list of strings). +‘children (&optional query)’ + Return non-nil if current heading has direct child headings. If + ‘QUERY’, test it against child headings. This selector may be + nested, e.g. to match grandchild headings. +‘descendants (&optional query)’ + Return non-nil if current heading has descendant headings. If + ‘QUERY’, test it against descendant headings. This selector may be + nested (if you can grok the nesting!). +‘done’ + Return non-nil if entry’s ‘TODO’ keyword is in ‘org-done-keywords’. +‘habit’ + Return non-nil if entry is a habit. +‘heading (&rest regexps)’ + Return non-nil if current entry’s heading matches all ‘REGEXPS’ + (regexp strings). +‘level (level-or-comparator &optional level)’ + Return non-nil if current heading’s outline level matches + arguments. The following forms are accepted: ‘(level NUMBER)’: + Matches if heading level is ‘NUMBER’. ‘(level NUMBER NUMBER)’: + Matches if heading level is equal to or between NUMBERs. ‘(level + COMPARATOR NUMBER)’: Matches if heading level compares to ‘NUMBER’ + with ‘COMPARATOR’. ‘COMPARATOR’ may be ‘<’, ‘<=’, ‘>’, or ‘>=’. +‘outline-path (&rest strings)’ + Return non-nil if current node’s outline path matches all of + ‘STRINGS’. Each string may appear as a substring in any part of + the node’s outline path. For example, the path Food/Fruits/Grapes + would match ‘(olp "Fruit" "Grape")’. + • Aliases: ‘olp’. +‘outline-path-segment (&rest strings)’ + Return non-nil if current node’s outline path matches ‘STRINGS’. + Matches ‘STRINGS’ as a contiguous segment of the outline path. + Each string is compared as a substring. For example the path + ‘Food/Fruits/Grapes’ would match ‘(olps "Fruit" "Grape")’ but not + ‘(olps "Food" "Grape")’. + • Aliases: ‘olps’. +‘path (&rest regexps)’ + Return non-nil if current heading’s buffer’s filename path matches + any of ‘REGEXPS’ (regexp strings). Without arguments, return + non-nil if buffer is file-backed. +‘priority (&optional comparator-or-priority priority)’ + Return non-nil if current heading has a certain priority. + ‘COMPARATOR-OR-PRIORITY’ should be either a comparator function, + like ‘<=’, or a priority string, like "A" (in which case (‘=’ will + be the comparator). If ‘COMPARATOR-OR-PRIORITY’ is a comparator, + ‘PRIORITY’ should be a priority string. If both arguments are nil, + return non-nil if heading has any defined priority. +‘property (property &optional value)’ + Return non-nil if current entry has ‘PROPERTY’ (a string), and + optionally ‘VALUE’ (a string). Note that property inheritance is + currently _not_ enabled for this predicate. If you need to test + with inheritance, you could use a custom predicate form, like + ‘(org-entry-get (point) "PROPERTY" 'inherit)’. +‘regexp (&rest regexps)’ + Return non-nil if current entry matches all of ‘REGEXPS’ (regexp + strings). Matches against entire entry, from beginning of its + heading to the next heading. +‘tags (&optional tags)’ + Return non-nil if current heading has one or more of ‘TAGS’ (a list + of strings). Tests both inherited and local tags. +‘tags-inherited (&optional tags)’ + Return non-nil if current heading’s inherited tags include one or + more of ‘TAGS’ (a list of strings). If ‘TAGS’ is nil, return + non-nil if heading has any inherited tags. + • Aliases: ‘inherited-tags’, ‘tags-i’, ‘itags’. +‘tags-local (&optional tags)’ + Return non-nil if current heading’s local tags include one or more + of ‘TAGS’ (a list of strings). If ‘TAGS’ is nil, return non-nil if + heading has any local tags. + • Aliases: ‘local-tags’, ‘tags-l’, ‘ltags’. +‘tags-all (tags)’ + Return non-nil if current heading includes all of ‘TAGS’. Tests + both inherited and local tags. + • Aliases: ‘tags&’. +‘todo (&optional keywords)’ + Return non-nil if current heading is a ‘TODO’ item. With + ‘KEYWORDS’, return non-nil if its keyword is one of ‘KEYWORDS’ (a + list of strings). When called without arguments, only matches + non-done tasks (i.e. does not match keywords in + ‘org-done-keywords’). + + +File: README.info, Node: Date/time predicates, Prev: Predicates, Up: Queries + +4.2.3 Date/time predicates +-------------------------- + +All of these predicates take optional keyword arguments ‘:from’, ‘:to:’, +and ‘:on’: + + • If ‘:from’, return non-nil if entry has a timestamp on or after + ‘:from’. + • If ‘:to’, return non-nil if entry has a timestamp on or before + ‘:to’. + • If ‘:on’, return non-nil if entry has a timestamp on date ‘:on’. + + Argument values should be either a number of days (positive to look +forward, or negative to look backward), a ‘ts’ struct, or a string +parseable by ‘parse-time-string’ (the string may omit the time value). + + • *Predicates* + ‘ts’ + Return non-nil if current entry has a timestamp in given + period. If no arguments are specified, return non-nil if + entry has any timestamp. + ‘ts-active, ts-a’ + Like ts, but only matches active timestamps. + ‘ts-inactive, ts-i’ + Like ts, but only matches inactive timestamps. + + The following predicates, in addition to the keyword arguments, can +also take a single argument, a number, which looks backward or forward a +number of days. The number can be negative to invert the direction. + + • *Backward-looking* + ‘clocked’ + Return non-nil if current entry was clocked in given period. + If no arguments are specified, return non-nil if entry was + clocked at any time. Note: Clock entries are expected to be + clocked out. Currently clocked entries (i.e. with unclosed + timestamp ranges) are ignored. + ‘closed’ + Return non-nil if current entry was closed in given period. + If no arguments are specified, return non-nil if entry was + closed at any time. + + • *Forward-looking* + ‘deadline’ + Return non-nil if current entry has deadline in given period. + If argument is auto, return non-nil if entry has deadline + within org-deadline-warning-days. If no arguments are + specified, return non-nil if entry has any deadline. + ‘planning’ + Return non-nil if current entry has planning timestamp in + given period (i.e. its deadline, scheduled, or closed + timestamp). If no arguments are specified, return non-nil if + entry is scheduled at any time. + ‘scheduled’ + Return non-nil if current entry is scheduled in given period. + If no arguments are specified, return non-nil if entry is + scheduled at any time. + + +File: README.info, Node: Functions / Macros, Prev: Queries, Up: Usage + +4.3 Functions / Macros +====================== + +* Menu: + +* Agenda-like views:: +* Listing / acting-on results:: + + +File: README.info, Node: Agenda-like views, Next: Listing / acting-on results, Up: Functions / Macros + +4.3.1 Agenda-like views +----------------------- + + 1. Function: ‘org-ql-block’ + + For use as a custom agenda block type in + ‘org-agenda-custom-commands’. For example, you could define a + custom series command like this, which would list all priority A + items tagged Emacs with to-do keyword SOMEDAY, followed by the + standard agenda view, in a single buffer: + + (setq org-agenda-custom-commands + '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" + ((org-ql-block '(and (todo "SOMEDAY") + (tags "Emacs") + (priority "A")) + ((org-ql-block-header "SOMEDAY :Emacs: High-priority"))) + (agenda))))) + + Which would be equivalent to a ‘tags-todo’ search like this: + + (setq org-agenda-custom-commands + '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" + ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY") + (agenda))))) + + However, the ‘org-ql-block’ version runs in about 1/5th the time. + + The variable org-ql-block-header may be bound to a string to use as + the block header, otherwise the header is formed automatically. + + +File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, Up: Functions / Macros + +4.3.2 Listing / acting-on results +--------------------------------- + + 1. Function: ‘org-ql-select’ + + _Arguments:_ ‘(buffers-or-files query &key action narrow sort)’ + + Return items matching ‘QUERY’ in ‘BUFFERS-OR-FILES’. + + ‘BUFFERS-OR-FILES’ is a one or a list of files and/or buffers. + + ‘QUERY’ is an ‘org-ql’ query sexp (quoted, since this is a + function). + + ‘ACTION’ is a function which is called on each matching entry with + point at the beginning of its heading. It may be: + + • ‘element’ or nil: Equivalent to ‘org-element-headline-parser’. + + • ‘element-with-markers’: Equivalent to calling + ‘org-element-headline-parser’, with markers added using + ‘org-ql--add-markers’. Suitable for formatting with + ‘org-ql-agenda--format-element’, allowing insertion into an + Org Agenda-like buffer. + + • A sexp, which will be byte-compiled into a lambda function. + + • A function symbol. + + If ‘NARROW’ is non-nil, buffers are not widened (the default is to + widen and search the entire buffer). + + ‘SORT’ is either nil, in which case items are not sorted; or one or + a list of defined ‘org-ql’ sorting methods (‘date’, ‘deadline’, + ‘scheduled’, ‘todo’, ‘priority’, or ‘random’); or a user-defined + comparator function that accepts two items as arguments and returns + nil or non-nil. + + Examples: + + ;; Return list of to-do headings in inbox file with tags and to-do keywords: + (org-ql-select "~/org/inbox.org" + '(todo) + :action #'org-get-heading) + ;; => ("TODO Practice leaping tall buildings in a single bound :personal:" ...) + + ;; Without tags and to-do keywords: + (org-ql-select "~/org/inbox.org" + '(todo) + :action '(org-get-heading t t)) + ;; => ("Practice leaping tall buildings in a single bound" ...) + + ;; Return WAITING heading elements in agenda files: + (org-ql-select (org-agenda-files) + '(todo "WAITING") + :action 'element) + ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) + + ;; Since `element' is the default for ACTION, it may be omitted: + (org-ql-select (org-agenda-files) + '(todo "WAITING")) + ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) + + 2. Function: ‘org-ql-query’ + + _Arguments:_ ‘(&key (select 'element-with-markers) from where + order-by narrow)’ + + Like ‘org-ql-select’, but arguments are named more like a ‘SQL’ + query. + + • ‘SELECT’ corresponds to the ‘org-ql-select’ argument ‘ACTION’. + • ‘FROM’ corresponds to the ‘org-ql-select’ argument + ‘BUFFERS-OR-FILES’. + • ‘WHERE’ corresponds to the ‘org-ql-select’ argument ‘QUERY’. + • ‘ORDER-BY’ corresponds to the ‘org-ql-select’ argument ‘SORT’, + which see. + • ‘NARROW’ corresponds to the ‘org-ql-select’ argument ‘NARROW’. + + Examples: + + ;; Return list of to-do headings in inbox file with tags and to-do keywords: + (org-ql-query + :select #'org-get-heading + :from "~/org/inbox.org" + :where '(todo)) + ;; => ("TODO Practice leaping tall buildings in a single bound :personal:" ...) + + ;; Without tags and to-do keywords: + (org-ql-query + :select '(org-get-heading t t) + :from "~/org/inbox.org" + :where '(todo)) + ;; => ("Practice leaping tall buildings in a single bound" ...) + + ;; Return WAITING heading elements in agenda files: + (org-ql-query + :select 'element + :from (org-agenda-files) + :where '(todo "WAITING")) + ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) + + ;; Since `element' is the default for SELECT, it may be omitted: + (org-ql-query + :from (org-agenda-files) + :where '(todo "WAITING")) + ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) + + 3. Macro: ‘org-ql’ + + _Arguments:_ ‘(buffers-or-files query &key sort narrow markers + action)’ + + Expands into a call to ‘org-ql-select’ with the same arguments. + For convenience, arguments should be unquoted. + + +File: README.info, Node: Changelog, Next: Notes, Prev: Usage, Up: Top + +5 Changelog +*********** + +_Note:_ Breaking changes may be made before version 1.0, but in the +event of major changes, attempts at backward compatibility will be made +with obsolescence declarations, translation of arguments, etc. Users +who need stability guarantees before 1.0 may choose to use tagged stable +releases. + +* Menu: + +* 0.4-pre: 04-pre. +* 0.3: 03. +* 0.2.3: 023. +* 0.2.2: 022. +* 0.2.1: 021. +* 0.2: 02. +* 0.1: 01. + + +File: README.info, Node: 04-pre, Next: 03, Up: Changelog + +5.1 0.4-pre +=========== + +*Added* + • Predicates outline-path (alias olp) and outline-path-segment (alias + olps). + • Info manual. + + *Internal* + • Added generic node data cache to speed up recursive, tree-based + queries. + + +File: README.info, Node: 03, Next: 023, Prev: 04-pre, Up: Changelog + +5.2 0.3 +======= + +*Added* + • Alternative, non-sexp query syntax for commands org-ql-search and + helm-org-ql. See . + • Command helm-org-ql. + • Command org-ql-sparse-tree, like org-sparse-tree for org-ql + queries. (Thanks to Akira Komamura (https://github.com/akirak).) + • Command org-ql-view-sidebar. + • Per-buffer, per-heading tag caching, which increases the speed of + tags-related queries by 6-7x. + • More tags-related predicates and aliases: + • For inherited tags: tags-inherited, inherited-tags, tags-i, + itags. + • For heading-local tags: tags-local, local-tags, tags-l, ltags. + • tags-all, tags&: Matches all given tags using boolean AND + (rather than boolean OR, which the tags predicate uses). + • Variable org-ql-block-header, which overrides the default header in + org-ql-block agenda blocks. + • Predicate (path). + • Option org-ql-views may now be customized in a guided, structured + way with the customization UI (e.g. + M-x customize-option RET org-ql-views RET, or press c in the + org-ql-view-sidebar buffer). + • Enable more Org Agenda commands in org-ql-view buffers (e.g. + setting deadlines and scheduling). (Fixes #35 + (https://github.com/alphapapa/org-ql/issues/35). Thanks to Milan + Zamazal (https://github.com/mz-pdm) and Mikhail Skorzhinskii + (https://github.com/mskorzhinskiy).) + • Function org-ql-select’s buffers-files argument can be a function + which returns a list of buffers and/or files. + + *Changed* + • Predicate heading now accepts multiple regexps, which are matched + with boolean AND. + • Predicate regexp now matches its regexp arguments with boolean AND. + • Package org-super-agenda is now a dependency. This removes the + need for awkward code to handle the case where it’s not installed, + and makes grouping features always available. Of course, the + global minor mode org-super-agenda-mode is not activated by org-ql, + so no behavior is changed in Org Agenda or org-ql; it only means + that commands like org-ql-search will always provide grouping when + called with the appropriate arguments. + + *Removed* + • Macro org-ql-agenda. Instead, use function org-ql-search. See + also command org-ql-view, etc. + + *Fixed* + • Predicate heading now matches only against heading text, i.e. not + including tags at the end of the line, to-do keyword, etc. + • Predicate todo now matches case-sensitively, avoiding + non-todo-keyword matches (e.g. a heading which begins Waiting on + will no longer match for a todo keyword WAITING). + • Interactive completion in org-ql-search. + + *Internal* + • Refactored code from file org-ql-agenda.el into files + org-ql-search.el and org-ql-view.el. Function and variable names + have been changed accordingly. + + +File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog + +5.3 0.2.3 +========= + +*Fixed* + • Priority queries could fail to match headings whose to-do keywords + had non-alphabetic characters, like TO-READ. + + +File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog + +5.4 0.2.2 +========= + +*Fixed* + • (deadline auto) selector matched entries whose deadlines had a + warning period that had not yet been entered + (org-deadline-warning-days too soon). + + +File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog + +5.5 0.2.1 +========= + +*Fixed* + • (descendants) selector matched against parent heading instead of + only descendants. + + +File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog + +5.6 0.2 +======= + +*Added* + • Function ‘org-ql-query’, like ‘org-ql-select’ but with arguments + named more like a SQL query. + • Bare strings like ‘"string"’ can be used in queries, which are + converted to ‘(regexp "string")’ automatically. + • Selector ‘(regexp)’ accepts multiple regexps to test. + • Macro ‘org-ql’ and functions ‘org-ql-query’ and ‘org-ql-select’ now + also accept a comparator function in their ‘:sort’ argument. + • Function ‘org-ql-block’, which works as an Org Agenda + series/composite/block command, usable in custom agenda commands + defined in variable ‘org-agenda-custom-commands’. (Inspired by + Benson Chu’s config + (https://github.com/pestctrl/emacs-config/blob/84c557982a860e86d6f67976a82ea776a7bd2c7a/config-org-new.org#my-own-agenda-renderer).) + • Function ‘org-ql-agenda--agenda’ optionally takes a list of entries + as an argument. + • Selectors ‘ts-a’ and ‘ts-i’, aliases for ‘ts-active’ and + ‘ts-inactive’. + • Selector ‘ts’ now accepts a ‘:type’ argument. + • Face org-ql-agenda-due-date. + • Selectors ‘(children)’ and ‘(descendants)’. + • Function ‘org-ql-search’ and macro ‘org-ql-agenda’ accept a + ‘:title’ argument, which is displayed in the header. + • Command ‘org-ql-search’ offers global ‘org-super-agenda-groups’ in + completion. + • Customization group ‘org-ql’. + • Command ‘org-ql-view’, which displays views saved to variable + ‘org-ql-views’, which can be saved from ‘org-ql-search’ buffers + with command ‘org-ql-search-save’, which is bound to C-x C-s in + view buffers. + • Variable ‘org-ql-view-map’, active in view buffers displayed by + ‘org-ql-search’, ‘org-ql-agenda’, and ‘org-ql-view’. + • random sort method. + • Save position when refreshing search buffers. + + *Changed* + • Function ‘org-ql-query’ renamed to ‘org-ql-select’. ‘org-ql-query’ + now refers to a new function. + • Macro ‘org-ql’ no longer accepts a ‘:markers’ argument. Instead, + use argument ‘:action element-with-markers’. See function + ‘org-ql-select’, which ‘org-ql’ calls. + • Selector ‘(todo)’ no longer matches "done" keywords when used + without arguments (i.e. the ones in variable ‘org-done-keywords’). + • Overhauled date/time-based predicates. See documentation for new + argument signatures. + + *Removed* + • Selector ‘(date)’, replaced by ‘(ts)’. + + *Fixed* + • Handle date ranges in date-based selectors. (Thanks to Cody + Goodman (https://github.com/codygman), Samuel W. Flint + (https://github.com/swflint), and Vikas Rawal + (https://github.com/vikasrawal).) + • Don’t overwrite bindings in org-agenda-mode-map. + • Don’t search buffers without headings, and show a message if the + user attempts it. + • Don’t search hidden/special buffers. + • Properly accept arbitrary sort functions in org-ql-select, etc. + (Fixes #37 (https://github.com/alphapapa/org-ql/issues/37). Thanks + to Milan Zamazal (https://github.com/mz-pdm).) + • Planning-line-related predicates searched too far into entries. + • Add autoloads. (Fixes #36 + (https://github.com/alphapapa/org-ql/pull/36/files#). Thanks to + Akira Komamura (https://github.com/akirak).) + + *Compatibility* + • Fixes for compatibility with Org 9.2. (Thanks to Ataias Pereira + Reis (https://github.com/ataias) and Daniel Kraus + (https://github.com/dakra).) + + *Internal* + • Optimizations for some query selectors, e.g. regexp and todo. + These can provide a significant improvement for some queries. See + benchmarks in notes.org (notes.org). + • Library ts (https://github.com/alphapapa/ts.el) is now used for + parsing and comparing timestamps. + + +File: README.info, Node: 01, Prev: 02, Up: Changelog + +5.7 0.1 +======= + +First tagged release. + + +File: README.info, Node: Notes, Next: License, Prev: Changelog, Up: Top + +6 Notes +******* + +* Menu: + +* Comparison with Org Agenda searches:: +* org-sidebar:: + + +File: README.info, Node: Comparison with Org Agenda searches, Next: org-sidebar, Up: Notes + +6.1 Comparison with Org Agenda searches +======================================= + +Of course, queries like these can already be written with Org Agenda +searches, but the syntax can be complex. For example, this query would +be difficult to write in a standard Org Agenda search, because it +matches against a to-do keyword _and_ a plain-text search. As described +in the advanced searching tutorial +(https://orgmode.org/worg/org-tutorials/advanced-searching.html#combining-metadata-and-full-text-queries), +it would require using ‘org-search-view’ with a query with specific +regular expression syntax, like this: + ++lisp +{^\*+\s-+TO-READ\s-} + + But with ‘org-ql-agenda’, you would write: + + (org-ql-agenda + (and (regexp "lisp") + (todo "TO-READ"))) + + +File: README.info, Node: org-sidebar, Prev: Comparison with Org Agenda searches, Up: Notes + +6.2 org-sidebar +=============== + +This package is used by org-sidebar +(https://github.com/alphapapa/org-sidebar), which presents a +customizable agenda-like view in a sidebar window. + + +File: README.info, Node: License, Prev: Notes, Up: Top + +7 License +********* + +GPLv3 + + + +Tag Table: +Node: Top225 +Node: Contents1337 +Node: Screenshots1485 +Node: Installation1603 +Node: Quelpa2241 +Node: Usage2684 +Node: Commands3594 +Node: org-ql-search3823 +Node: helm-org-ql5416 +Node: org-ql-view5828 +Node: org-ql-view-sidebar6026 +Node: org-ql-view-recent-items6382 +Node: org-ql-sparse-tree6866 +Node: Queries7666 +Node: Non-sexp query syntax8508 +Node: Predicates10008 +Node: Date/time predicates14865 +Node: Functions / Macros17500 +Node: Agenda-like views17687 +Node: Listing / acting-on results19092 +Node: Changelog23694 +Node: 04-pre24201 +Node: 0324505 +Node: 02327481 +Node: 02227707 +Node: 02127973 +Node: 0228170 +Node: 0132203 +Node: Notes32302 +Node: Comparison with Org Agenda searches32464 +Node: org-sidebar33335 +Node: License33614 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: From 7fa0d83a547cee5ea58b2cf3d337530c7d5788c6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 11:01:09 -0500 Subject: [PATCH 009/560] Add: helm-org-ql-source, org-ql-search-directories-files, etc. --- README.org | 2 ++ helm-org-ql.el | 73 +++++++++++++++++++++++++----------------------- org-ql-search.el | 47 +++++++++++++++++++++++++++++-- org-ql.el | 2 +- org-ql.info | 25 ++++++++++------- 5 files changed, 101 insertions(+), 48 deletions(-) diff --git a/README.org b/README.org index a7258dc..be50959 100644 --- a/README.org +++ b/README.org @@ -375,6 +375,8 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Added* + Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + Info manual. ++ Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. ++ Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/helm-org-ql.el b/helm-org-ql.el index 96604cb..d8bdb0c 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -33,6 +33,7 @@ (require 'org) (require 'org-ql) +(require 'org-ql-search) ;; (require 'helm) ;; (require 'helm-org) @@ -125,51 +126,20 @@ Is transformed into this query: (let ((boolean (if current-prefix-arg 'or boolean)) (helm-input-idle-delay helm-org-ql-input-idle-delay)) (helm :prompt (format "Query (boolean %s): " (-> boolean symbol-name upcase)) - :sources - ;; Expansion of `helm-build-sync-source' macro. - (helm-make-source name 'helm-source-sync - :candidates (lambda nil - (let* ((query (org-ql--plain-query helm-pattern boolean)) - (window-width (window-width (helm-window)))) - (when query - (with-current-buffer (helm-buffer-get) - (setq helm-org-ql-buffers-files buffers-files)) - (ignore-errors - ;; Ignore errors that might be caused by partially typed queries. - - ;; FIXME: This doesn't prevent warnings that are errors occurring during - ;; byte-compilation due to partially typed values which can't be correctly - ;; pre-processed, e.g. "ts:to=2019-01-0", which can't be parsed into a - ;; timestamp. A "*Compile-Log*" buffer is displayed with "Error: Wrong type - ;; argument: integerp, nil". With my Helm settings, it's hidden as soon as - ;; the query is typed correctly, so it's tolerable, but I'd prefer to fix it. - ;; I haven't found a way to ignore the error/warning; `with-no-warnings' has - ;; no effect, and we're already using `ignore-errors'. The only solution I - ;; can think of would be to ignore the errors/warnings higher up the chain - ;; where byte-compilation is actually done, but it might not be a good idea - ;; to always ignore such errors/warnings. - (org-ql-select buffers-files query - :action (list 'helm-org-ql--heading window-width)))))) - :match #'identity - :fuzzy-match nil - :multimatch nil - :volatile t - :keymap helm-org-ql-map - :action helm-org-ql-actions)))) + :sources (helm-org-ql-source buffers-files :name name)))) ;;;###autoload (defun helm-org-ql-agenda-files () "Search agenda files with `helm-org-ql', which see." (interactive) - (helm-org-ql (org-agenda-files) :name "helm-org-ql-agenda-files")) + (helm-org-ql (org-agenda-files) :name "Org Agenda Files")) ;;;###autoload (defun helm-org-ql-org-directory () "Search Org files in `org-directory' with `helm-org-ql'." (interactive) - (helm-org-ql (directory-files org-directory 'full - (rx ".org" eos)) - :name "helm-org-ql-org-directory")) + (helm-org-ql (org-ql-search-directories-files) + :name "Org Directory Files")) (defun helm-org-ql-show-marker (marker) "Show heading at MARKER." @@ -198,6 +168,39 @@ Is transformed into this query: ;;;; Functions +(cl-defun helm-org-ql-source (buffers-files &key (name "helm-org-ql")) + "Return Helm source named NAME that searches BUFFERS-FILES with `helm-org-ql'." + ;; Expansion of `helm-build-sync-source' macro. + (helm-make-source name 'helm-source-sync + :candidates (lambda nil + (let* ((query (org-ql--plain-query helm-pattern)) + (window-width (window-width (helm-window)))) + (when query + (with-current-buffer (helm-buffer-get) + (setq helm-org-ql-buffers-files buffers-files)) + (ignore-errors + ;; Ignore errors that might be caused by partially typed queries. + + ;; FIXME: This doesn't prevent warnings that are errors occurring during + ;; byte-compilation due to partially typed values which can't be correctly + ;; pre-processed, e.g. "ts:to=2019-01-0", which can't be parsed into a + ;; timestamp. A "*Compile-Log*" buffer is displayed with "Error: Wrong type + ;; argument: integerp, nil". With my Helm settings, it's hidden as soon as + ;; the query is typed correctly, so it's tolerable, but I'd prefer to fix it. + ;; I haven't found a way to ignore the error/warning; `with-no-warnings' has + ;; no effect, and we're already using `ignore-errors'. The only solution I + ;; can think of would be to ignore the errors/warnings higher up the chain + ;; where byte-compilation is actually done, but it might not be a good idea + ;; to always ignore such errors/warnings. + (org-ql-select buffers-files query + :action (list 'helm-org-ql--heading window-width)))))) + :match #'identity + :fuzzy-match nil + :multimatch nil + :volatile t + :keymap helm-org-ql-map + :action helm-org-ql-actions)) + (defun helm-org-ql--heading (window-width) "Return string for Helm for heading at point. WINDOW-WIDTH should be the width of the Helm window." diff --git a/org-ql-search.el b/org-ql-search.el index 45f349a..9ef07c0 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -30,6 +30,7 @@ (require 'cl-lib) (require 'dash) +(require 'f) (require 'org-super-agenda) (require 's) @@ -41,6 +42,30 @@ (defvar org-ql-block-header nil "An optional string to override the default header in `org-ql-block' agenda blocks.") +;;;; Customization + +(defgroup org-ql-search nil + "Options for `org-ql-search' commands." + :group 'org-ql) + +(defcustom org-ql-search-directories-files-regexp "\.org$" + "Regular expression to match Org filenames in `org-directory'. +Files matching this regexp will be searched. By default, +\".org\" files are matched, but you may also select to include +\".org_archive\" files, or use a custom regexp." + :type '(radio (const :tag "Normal \".org\" files" :value "\.org$") + (const :tag "Also include \".org_archive\" files" "\.org\\(_archive\\)?$") + (string :tag "Custom regular expression"))) + +(defcustom org-ql-search-directories-files-recursive nil + "Recurse into subdirectories by default in `org-ql-search-directories-files'. +This should probably be disabled by default, because +e.g. `org-directory' may include deeply nested directories of +non-Org files, such as a \".git\" directory, Org attachments +directories, etc, which would make it slow to list the +`org-directory' files recursively." + :type 'boolean) + ;;;; Commands ;;;###autoload @@ -91,6 +116,7 @@ Interactively, may also be: - `buffer': search the current buffer - `all': search all Org buffers - `agenda': search buffers returned by the function `org-agenda-files' +- `directory': search Org files in `org-directory' - An expression which evaluates to a list of files/buffers - A space-separated list of file or buffer names @@ -114,12 +140,13 @@ display the results. By default, the value of necessary." (declare (indent defun)) (interactive (list (pcase-exhaustive (completing-read "Buffers/Files: " - (list 'buffer 'agenda 'all) + (list 'buffer 'agenda 'directory 'all) nil t) + ((or "" "buffer") (current-buffer)) ("agenda" (org-agenda-files)) ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) (buffer-list))) - ((or "" "buffer") (current-buffer)) + ("directory" (org-ql-search-directories-files)) ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) (else (s-split (rx (1+ space)) else))) (read-string "Query: ") @@ -205,6 +232,22 @@ automatically from the query." ;;;###autoload (defalias 'org-ql-block 'org-ql-search-block) +;;;; Functions + +(cl-defun org-ql-search-directories-files (&key (directories (list org-directory)) + (recurse org-ql-search-directories-files-recursive) + (regexp org-ql-search-directories-files-regexp)) + "Return list of matching files in DIRECTORIES, a list of directory paths. +When RECURSE is non-nil, recurse into subdirectories. When +REGEXP is non-nil, only return files that match REGEXP." + (let ((files (->> directories + (--map (f-files it nil recurse)) + -flatten))) + (if regexp + (--select (string-match regexp it) + files) + files))) + ;;;; Footer (provide 'org-ql-search) diff --git a/org-ql.el b/org-ql.el index 65f1ff9..c7b9ea3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql ;; Version: 0.4-pre -;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: diff --git a/org-ql.info b/org-ql.info index f585e33..3632511 100644 --- a/org-ql.info +++ b/org-ql.info @@ -690,6 +690,11 @@ File: README.info, Node: 04-pre, Next: 03, Up: Changelog • Predicates outline-path (alias olp) and outline-path-segment (alias olps). • Info manual. + • Command ‘org-ql-search’ can search files in ‘org-directory’; + customization options are available in the ‘org-ql-search’ group. + • Function ‘helm-org-ql-source’, which returns a Helm source that + searches given buffers/files with ‘helm-org-ql’. It can be used + for custom Helm commands that search certain files. *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -959,16 +964,16 @@ Node: Agenda-like views17687 Node: Listing / acting-on results19092 Node: Changelog23694 Node: 04-pre24201 -Node: 0324505 -Node: 02327481 -Node: 02227707 -Node: 02127973 -Node: 0228170 -Node: 0132203 -Node: Notes32302 -Node: Comparison with Org Agenda searches32464 -Node: org-sidebar33335 -Node: License33614 +Node: 0324862 +Node: 02327838 +Node: 02228064 +Node: 02128330 +Node: 0228527 +Node: 0132560 +Node: Notes32659 +Node: Comparison with Org Agenda searches32821 +Node: org-sidebar33692 +Node: License33971  End Tag Table From 553c22c3ac390117e095ec78fd756a713acdc641 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 18:20:29 -0500 Subject: [PATCH 010/560] Add: Adjust search parameters in view buffers --- README.org | 3 +- org-ql-search.el | 112 +++++++++++++++++++++++++++-------------------- org-ql-view.el | 50 ++++++++++++++------- org-ql.info | 53 +++++++++++----------- 4 files changed, 128 insertions(+), 90 deletions(-) diff --git a/README.org b/README.org index be50959..f489562 100644 --- a/README.org +++ b/README.org @@ -105,7 +105,7 @@ Read ~QUERY~ and search with ~org-ql~. Interactively, prompt for these variable ~SORT~: One or a list of ~org-ql~ sorting functions, like ~date~ or ~priority~. *Bindings:* Keys bound in results buffer. -+ =g=: Refresh results. ++ =g=: Refresh results. With prefix, prompt to adjust search parameters. + =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). *Note:* The view buffer is currently put in ~org-agenda-mode~, which means that /some/ Org Agenda commands work, such as jumping to entries and changing item priorities (without necessarily updating the view). This feature is experimental and not guaranteed to work correctly with all commands. (It works to the extent it does because the appropriate text properties are placed on each item, imitating an Agenda buffer.) @@ -376,6 +376,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + Info manual. + Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. ++ Command ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. *Internal* diff --git a/org-ql-search.el b/org-ql-search.el index 9ef07c0..eb4e550 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -139,28 +139,39 @@ display the results. By default, the value of `org-ql-view-buffer' is used, and a new buffer is created if necessary." (declare (indent defun)) - (interactive (list (pcase-exhaustive (completing-read "Buffers/Files: " - (list 'buffer 'agenda 'directory 'all) - nil t) - ((or "" "buffer") (current-buffer)) - ("agenda" (org-agenda-files)) - ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) - (buffer-list))) - ("directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) - (else (s-split (rx (1+ space)) else))) - (read-string "Query: ") - :narrow (eq current-prefix-arg '(4)) + (interactive (list (if (and org-ql-view-buffers-files + (bufferp org-ql-view-buffers-files)) + ;; Buffers can't be input by name, so if the default value is a buffer, just use it. + ;; TODO: Find a way to fix this. + org-ql-view-buffers-files + (pcase-exhaustive (completing-read "Buffers/Files: " + (list 'buffer 'agenda 'directory 'all) + nil nil (when org-ql-view-buffers-files + (prin1-to-string (cons 'list org-ql-view-buffers-files)))) + ((or "" "buffer") (current-buffer)) + ("agenda" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("directory" (org-ql-search-directories-files)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else)))) + (read-string "Query: " (when org-ql-view-query + (format "%S" org-ql-view-query))) + :narrow (or org-ql-view-narrow (eq current-prefix-arg '(4))) :super-groups (when (bound-and-true-p org-super-agenda-auto-selector-keywords) - (pcase (completing-read "Group by: " - (append (list "Don't group" - "Global super-groups") - (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6))) - nil t) - ("Global super-groups" org-super-agenda-groups) - ((or "" "Don't group") nil) - (property (list (list (intern (concat ":auto-" property))))))) + (let ((keywords (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + (pcase (completing-read "Group by: " + (append (list "Don't group" + "Global super-groups") + keywords) + nil nil (when org-ql-view-super-groups + (format "%S" org-ql-view-super-groups))) + ("Global super-groups" org-super-agenda-groups) + ((or "" "Don't group") nil) + ((and keyword (guard (member keyword keywords))) + (list (list (intern (concat ":auto-" keyword))))) + (else (read else))))) :sort (pcase (completing-read "Sort by: " (list "Don't sort" "date" @@ -168,35 +179,42 @@ necessary." "priority" "scheduled" "todo") - nil t) + nil t (when org-ql-view-sort + (prin1-to-string org-ql-view-sort))) ((or "" "Don't sort") nil) (sort (intern sort))))) - (let* ((query (cl-etypecase query - (string (if (string-match-p (rx bos (1+ alpha) ":") query) + ;; NOTE: Using `with-temp-buffer' is a hack to work around the fact that `make-local-variable' + ;; does not work reliably from inside a `let' form when the target buffer is current on entry + ;; to or exit from the `let', even though `make-local-variable' is actually done in + ;; `org-ql-view--display'. So we do all this within a temp buffer, which works around it. + (with-temp-buffer + (let* ((query (cl-etypecase query + (string (if (or (string-prefix-p "(" query) + (string-prefix-p "\"" query)) + ;; Read sexp query. + (read query) ;; Parse non-sexp query into sexp query. - (org-ql--plain-query query) - ;; Read sexp query. - (read query))) - (list query))) - (results (org-ql-select buffers-files query - :action 'element-with-markers - :narrow narrow - :sort sort)) - (strings (-map #'org-ql-view--format-element results)) - (buffer (or buffer (format "%s %s*" org-ql-view-buffer-name-prefix (or title query)))) - (header (org-ql-view--header-line-format buffers-files query title)) - ;; Bind variables for `org-ql-view--display' to set. - (org-ql-view-buffers-files buffers-files) - (org-ql-view-query query) - (org-ql-view-sort sort) - (org-ql-view-narrow narrow) - (org-ql-view-super-groups super-groups) - (org-ql-view-title title)) - (when super-groups - (let ((org-super-agenda-groups super-groups)) - (setf strings (org-super-agenda--group-items strings)))) - (org-ql-view--display :buffer buffer :header header - :string (s-join "\n" strings)))) + (org-ql--plain-query query))) + (list query))) + (results (org-ql-select buffers-files query + :action 'element-with-markers + :narrow narrow + :sort sort)) + (strings (-map #'org-ql-view--format-element results)) + (buffer (or buffer (format "%s %s*" org-ql-view-buffer-name-prefix (or title query)))) + (header (org-ql-view--header-line-format buffers-files query title)) + ;; Bind variables for `org-ql-view--display' to set. + (org-ql-view-buffers-files buffers-files) + (org-ql-view-query query) + (org-ql-view-sort sort) + (org-ql-view-narrow narrow) + (org-ql-view-super-groups super-groups) + (org-ql-view-title title)) + (when super-groups + (let ((org-super-agenda-groups super-groups)) + (setf strings (org-super-agenda--group-items strings)))) + (org-ql-view--display :buffer buffer :header header + :string (s-join "\n" strings))))) (defun org-ql-search-block (query) "Insert items for QUERY into current buffer. diff --git a/org-ql-view.el b/org-ql-view.el index d65a7a7..9e57e0d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -266,18 +266,27 @@ TYPE may be `ts', `ts-active', `ts-inactive', `clocked', or 'face '(:weight bold :inherit highlight)) (org-ql-view key)))) -(defun org-ql-view-refresh () - "Refresh current `org-ql-search' buffer." - (interactive) - (let ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) - (old-pos (point))) - (org-ql-search org-ql-view-buffers-files - org-ql-view-query - :sort org-ql-view-sort - :narrow org-ql-view-narrow - :super-groups org-ql-view-super-groups - :title org-ql-view-title - :buffer (current-buffer)) +(defun org-ql-view-refresh (&optional prompt) + "Refresh current `org-ql-search' buffer. +If PROMPT is non-nil (interactively, with prefix), prompt to +update search arguments." + (interactive "P") + (let* ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) + (old-pos (point)) + (defaults (list org-ql-view-buffers-files + org-ql-view-query + :sort org-ql-view-sort + :narrow org-ql-view-narrow + :super-groups org-ql-view-super-groups + :title org-ql-view-title)) + (org-ql-view-buffer (current-buffer))) + (if prompt + (call-interactively #'org-ql-search) + (apply #'org-ql-search defaults)) + ;; Now in the results buffer. + (rename-buffer (format "%s %s*" + org-ql-view-buffer-name-prefix + (or org-ql-view-title org-ql-view-query))) (goto-char (point-min)) (or (when (search-forward current-line nil t) (beginning-of-line)) @@ -338,17 +347,24 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', `org-ql-view-query', `org-ql-view-sort', `org-ql-view-narrow', `org-ql-view-super-groups', `org-ql-title.'" (declare (indent defun)) - (let* ((buffer (cl-etypecase buffer + (let* ((vars (list 'org-ql-view-buffers-files 'org-ql-view-query + 'org-ql-view-sort 'org-ql-view-narrow + 'org-ql-view-super-groups 'org-ql-view-title)) + ;; Save the values of variables which are set buffer-locally in the + ;; results buffer, which we want to override and set buffer-locally again. + (vals (cl-loop for symbol in vars + collect (cons symbol (symbol-value symbol)))) + (buffer (cl-etypecase buffer (string (org-ql-view--buffer buffer)) (null (org-ql-view--buffer buffer)) (buffer buffer)))) (with-current-buffer buffer (use-local-map org-ql-view-map) ;; Prepare buffer, saving data for refreshing. - (cl-loop for symbol in (list 'org-ql-view-buffers-files 'org-ql-view-query - 'org-ql-view-sort 'org-ql-view-narrow - 'org-ql-view-super-groups 'org-ql-view-title) - do (set (make-local-variable symbol) (symbol-value symbol))) + (cl-loop for symbol in vars + do (progn + (kill-local-variable symbol) + (set (make-local-variable symbol) (alist-get symbol vals nil nil #'equal)))) (setf header-line-format header) ;; Clear buffer, insert entries, etc. (let ((inhibit-read-only t)) diff --git a/org-ql.info b/org-ql.info index 3632511..d7c135f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -216,7 +216,8 @@ Interactively, with prefix, leave narrowed. ‘priority’. *Bindings:* Keys bound in results buffer. - • g: Refresh results. + • g: Refresh results. With prefix, prompt to adjust search + parameters. • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with command ‘org-ql-view’). @@ -692,6 +693,8 @@ File: README.info, Node: 04-pre, Next: 03, Up: Changelog • Info manual. • Command ‘org-ql-search’ can search files in ‘org-directory’; customization options are available in the ‘org-ql-search’ group. + • Command ‘org-ql-view-refresh’ can be called with a prefix argument + to adjust search parameters. • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used for custom Helm commands that search certain files. @@ -950,30 +953,30 @@ Node: Quelpa2241 Node: Usage2684 Node: Commands3594 Node: org-ql-search3823 -Node: helm-org-ql5416 -Node: org-ql-view5828 -Node: org-ql-view-sidebar6026 -Node: org-ql-view-recent-items6382 -Node: org-ql-sparse-tree6866 -Node: Queries7666 -Node: Non-sexp query syntax8508 -Node: Predicates10008 -Node: Date/time predicates14865 -Node: Functions / Macros17500 -Node: Agenda-like views17687 -Node: Listing / acting-on results19092 -Node: Changelog23694 -Node: 04-pre24201 -Node: 0324862 -Node: 02327838 -Node: 02228064 -Node: 02128330 -Node: 0228527 -Node: 0132560 -Node: Notes32659 -Node: Comparison with Org Agenda searches32821 -Node: org-sidebar33692 -Node: License33971 +Node: helm-org-ql5471 +Node: org-ql-view5883 +Node: org-ql-view-sidebar6081 +Node: org-ql-view-recent-items6437 +Node: org-ql-sparse-tree6921 +Node: Queries7721 +Node: Non-sexp query syntax8563 +Node: Predicates10063 +Node: Date/time predicates14920 +Node: Functions / Macros17555 +Node: Agenda-like views17742 +Node: Listing / acting-on results19147 +Node: Changelog23749 +Node: 04-pre24256 +Node: 0325029 +Node: 02328005 +Node: 02228231 +Node: 02128497 +Node: 0228694 +Node: 0132727 +Node: Notes32826 +Node: Comparison with Org Agenda searches32988 +Node: org-sidebar33859 +Node: License34138  End Tag Table From 13723f81634426e68322dc727e015ccf2b0053ab Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Oct 2019 22:45:39 -0500 Subject: [PATCH 011/560] Change: (helm-org-ql) Disable highlighting Doesn't work properly because input contains predicates and keywords that shouldn't be highlighted. Might try to fix it someday to only use args to (regexp) and (heading). --- helm-org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/helm-org-ql.el b/helm-org-ql.el index d8bdb0c..7feea75 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -197,6 +197,7 @@ Is transformed into this query: :match #'identity :fuzzy-match nil :multimatch nil + :nohighlight t :volatile t :keymap helm-org-ql-map :action helm-org-ql-actions)) From da9be833264b85b052ecfc7ced542eff5d2ef342 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 8 Oct 2019 16:45:19 -0500 Subject: [PATCH 012/560] Add: helm-org-ql-views, helm-source-org-ql-views --- README.org | 1 + helm-org-ql.el | 15 +++++++++++++++ org-ql.info | 22 ++++++++++++---------- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/README.org b/README.org index f489562..adcb304 100644 --- a/README.org +++ b/README.org @@ -378,6 +378,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. + Command ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. ++ Command ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/helm-org-ql.el b/helm-org-ql.el index 7feea75..26beab9 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -66,6 +66,15 @@ "Keymap for `helm-org-ql' sessions. Based on `helm-map'.") +(defvar helm-source-org-ql-views + (helm-build-sync-source "Org QL Views" + :candidates (lambda () + (->> org-ql-views + (-map #'car) + (-sort #'string<))) + :action (list (cons "Show view" #'org-ql-view))) + "Helm source for `org-ql-views'.") + (defvar-local helm-org-ql-buffers-files nil "Used for `helm-org-ql-save'.") @@ -166,6 +175,12 @@ Is transformed into this query: (query (org-ql--plain-query helm-pattern))) (helm-run-after-exit #'org-ql-search buffers-files query))) +;;;###autoload +(defun helm-org-ql-views () + "Show an `org-ql' view selected with Helm." + (interactive) + (helm :sources helm-source-org-ql-views)) + ;;;; Functions (cl-defun helm-org-ql-source (buffers-files &key (name "helm-org-ql")) diff --git a/org-ql.info b/org-ql.info index d7c135f..753c58e 100644 --- a/org-ql.info +++ b/org-ql.info @@ -698,6 +698,8 @@ File: README.info, Node: 04-pre, Next: 03, Up: Changelog • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used for custom Helm commands that search certain files. + • Command ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ + selected with Helm. *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -967,16 +969,16 @@ Node: Agenda-like views17742 Node: Listing / acting-on results19147 Node: Changelog23749 Node: 04-pre24256 -Node: 0325029 -Node: 02328005 -Node: 02228231 -Node: 02128497 -Node: 0228694 -Node: 0132727 -Node: Notes32826 -Node: Comparison with Org Agenda searches32988 -Node: org-sidebar33859 -Node: License34138 +Node: 0325132 +Node: 02328108 +Node: 02228334 +Node: 02128600 +Node: 0228797 +Node: 0132830 +Node: Notes32929 +Node: Comparison with Org Agenda searches33091 +Node: org-sidebar33962 +Node: License34241  End Tag Table From e9e756331cfcce89455adfacac677f7dc2a4356c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 8 Oct 2019 20:55:51 -0500 Subject: [PATCH 013/560] Fix: (--outline-path) Always return a string org-heading-components returns nil for a heading without heading text, which causes string-match to signal an error. So we'll match the regexp ourselves and return an empty string in that case. Should be slightly faster, anyway. --- org-ql.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index c7b9ea3..db3fb85 100644 --- a/org-ql.el +++ b/org-ql.el @@ -429,7 +429,10 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." (defun org-ql--outline-path () "Return outline path for heading at point." (save-excursion - (let ((heading (nth 4 (org-heading-components)))) + (let ((heading (save-match-data + (if (looking-at org-complex-heading-regexp) + (or (match-string 4) "") + "")))) (if (org-up-heading-safe) ;; MAYBE: It seems wrong to call the cache function from ;; inside this function, like a violation of separation of From a60c238417e7bd65c1d84625fd2cb0dbd0ed7a87 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 8 Oct 2019 21:02:18 -0500 Subject: [PATCH 014/560] Fix: (org-ql-search) Bind print-length in interactive form The list of buffers/files must always be printed completely. --- org-ql-search.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index eb4e550..e7b372d 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -147,7 +147,8 @@ necessary." (pcase-exhaustive (completing-read "Buffers/Files: " (list 'buffer 'agenda 'directory 'all) nil nil (when org-ql-view-buffers-files - (prin1-to-string (cons 'list org-ql-view-buffers-files)))) + (let ((print-length nil)) + (prin1-to-string (cons 'list org-ql-view-buffers-files))))) ((or "" "buffer") (current-buffer)) ("agenda" (org-agenda-files)) ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) From 37ba30c9693ba5ea9e2928c9afdd9892ffab3153 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 9 Oct 2019 13:10:40 -0500 Subject: [PATCH 015/560] Add: src predicate --- README.org | 2 ++ org-ql.el | 54 ++++++++++++++++++++++++++++++++++++++++++++ org-ql.info | 37 +++++++++++++++++------------- tests/test-org-ql.el | 3 +++ 4 files changed, 80 insertions(+), 16 deletions(-) diff --git a/README.org b/README.org index adcb304..277f489 100644 --- a/README.org +++ b/README.org @@ -189,6 +189,7 @@ Arguments are listed next to predicate names, where applicable. + =priority (&optional comparator-or-priority priority)= :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. + =property (property &optional value)= :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. + =regexp (&rest regexps)= :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. ++ ~src (&optional lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. + =tags (&optional tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. + =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags. - Aliases: ~inherited-tags~, ~tags-i~, ~itags~. @@ -379,6 +380,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Command ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. + Command ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. ++ Predicate ~src~, which matches Org Babel source blocks. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql.el b/org-ql.el index db3fb85..4f88e2d 100644 --- a/org-ql.el +++ b/org-ql.el @@ -747,6 +747,13 @@ replace the clause with a preamble." ;; (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":" (1+ (not (or space ":"))) ":" ;; (1+ space) (minimal-match (1+ not-newline)) eol))) ;; element) + + ;; Src blocks. + (`(src ,lang . ,_) + (setq org-ql-preamble (org-ql--format-src-block-regexp lang)) + ;; Always check contents with predicate. + element) + (`(scheduled . ,_) (setq org-ql-preamble org-scheduled-time-regexp) ;; Return element, because the predicate still needs testing. @@ -781,6 +788,29 @@ replace the clause with a preamble." (query (-flatten-n 1 query)))) (list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold)))))) +(defun org-ql--format-src-block-regexp (&optional lang) + "Return regexp equivalent to `org-babel-src-block-regexp' with LANG filled in." + ;; I couldn't find a way to match block contents without the regexp + ;; also matching past the end of the block and into later blocks. Even + ;; using `minimal-match' in several different combinations didn't work. + ;; So matching contents will have to be done with the predicate. + (rx-to-string `(seq bol (group (zero-or-more (any " "))) + "#+begin_src" + (one-or-more (any " ")) + ,lang + (zero-or-more (any " ")) + (group (or (seq (zero-or-more (not (any "\n\":"))) + "\"" + (zero-or-more (not (any "\n\"*"))) + "\"" + (zero-or-more (not (any "\n\":")))) + (zero-or-more (not (any "\n\":"))))) + (group (zero-or-more (not (any "\n")))) "\n" + (63 (group (*\? (not (any ""))) "\n")) + (zero-or-more (any " ")) + "#+end_src") + t)) + (defmacro org-ql--from-to-on () "For internal use. Expands into a form that processes arguments to timestamp-related @@ -1102,6 +1132,30 @@ priority B)." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) +(org-ql--defpred src (&optional lang &rest regexps) + "Return non-nil if current entry contains an Org source block matching all of REGEXPS. +If LANG is non-nil, the block must be in that language." + (catch 'return + (save-excursion + (save-match-data + (when (re-search-forward org-babel-src-block-regexp (org-entry-end-position) t) + (when lang + (unless (string= lang (match-string 2)) + (throw 'return nil))) + (if regexps + (let ((contents-beg (progn + (goto-char (match-beginning 0)) + (forward-line 1) + (point))) + (contents-end (progn + (goto-char (match-end 0)) + (point-at-bol)))) + (cl-loop for re in regexps + do (goto-char contents-beg) + always (re-search-forward re contents-end t))) + ;; No regexps to check: return non-nil. + t)))))) + ;;;;;; Timestamps ;; TODO: Remove the _on vars from these arg lists. I think they're not diff --git a/org-ql.info b/org-ql.info index 753c58e..fc04f59 100644 --- a/org-ql.info +++ b/org-ql.info @@ -410,6 +410,10 @@ Arguments are listed next to predicate names, where applicable. Return non-nil if current entry matches all of ‘REGEXPS’ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. +‘‘src (&optional lang regexps)’’ + Return non-nil if current entry contains an Org Babel source block. + If ‘LANG’ is non-nil, match blocks of that language. If ‘REGEXPS’ + is non-nil, require that block’s contents match all regexps. ‘tags (&optional tags)’ Return non-nil if current heading has one or more of ‘TAGS’ (a list of strings). Tests both inherited and local tags. @@ -700,6 +704,7 @@ File: README.info, Node: 04-pre, Next: 03, Up: Changelog for custom Helm commands that search certain files. • Command ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ selected with Helm. + • Predicate ‘src’, which matches Org Babel source blocks. *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -963,22 +968,22 @@ Node: org-ql-sparse-tree6921 Node: Queries7721 Node: Non-sexp query syntax8563 Node: Predicates10063 -Node: Date/time predicates14920 -Node: Functions / Macros17555 -Node: Agenda-like views17742 -Node: Listing / acting-on results19147 -Node: Changelog23749 -Node: 04-pre24256 -Node: 0325132 -Node: 02328108 -Node: 02228334 -Node: 02128600 -Node: 0228797 -Node: 0132830 -Node: Notes32929 -Node: Comparison with Org Agenda searches33091 -Node: org-sidebar33962 -Node: License34241 +Node: Date/time predicates15182 +Node: Functions / Macros17817 +Node: Agenda-like views18004 +Node: Listing / acting-on results19409 +Node: Changelog24011 +Node: 04-pre24518 +Node: 0325461 +Node: 02328437 +Node: 02228663 +Node: 02128929 +Node: 0229126 +Node: 0133159 +Node: Notes33258 +Node: Comparison with Org Agenda searches33420 +Node: org-sidebar34291 +Node: License34570  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 66c3053..84ebadc 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -656,6 +656,9 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((scheduled :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) + ;; TODO: Test (src) predicate. That will require modifying test data, which will be a + ;; significant hassle. Manual testing shows that the predicate appears to work properly. + (describe "(todo)" (org-ql-it "without arguments" From 8e6f221063a514d1991e926616bc116bb7c49acd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 9 Oct 2019 14:45:24 -0500 Subject: [PATCH 016/560] Fix: Require map Thanks to Brian Leung (@leungbk). See #49. --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index 4f88e2d..f80b39a 100644 --- a/org-ql.el +++ b/org-ql.el @@ -42,6 +42,7 @@ (require 'dash) (require 'dash-functional) +(require 'map) (require 'ts) ;;;; Compatibility From 6b2004e678793a16767e405d341ff751a706d505 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 9 Oct 2019 17:21:47 -0500 Subject: [PATCH 017/560] Change/Fix: (src) predicate Use keyword args, fix non-sexp syntax and searching. --- README.org | 25 +++++++++++++------------ org-ql.el | 31 ++++++++++++++++++++++++++----- org-ql.info | 41 +++++++++++++++++++++-------------------- 3 files changed, 60 insertions(+), 37 deletions(-) diff --git a/README.org b/README.org index 1ecf6be..c57321b 100644 --- a/README.org +++ b/README.org @@ -153,17 +153,18 @@ An =org-ql= query is a lisp form which may contain arbitrary lisp forms, as well The command =org-ql-search= also accepts, and the command =helm-org-ql= only accepts, an alternative, non-sexp query syntax. The syntax is simple, and a few examples of queries in both syntaxes should suffice. By default, when multiple predicates are used, they are combined with boolean =and=. -| Sexp syntax | Non-sexp syntax | -|-------------------------------------------------+-----------------------------------------| -| ~(todo)~ | ~todo:~ | -| ~(todo "SOMEDAY")~ | ~todo:SOMEDAY~ | -| ~(todo "SOMEDAY" "WAITING")~ | ~todo:SOMEDAY,WAITING~ | -| ~(ts :on today)~ | ~ts:on=today~ | -| ~(ts-active :from "2017-01-01" :to "2018-01-01")~ | ~ts-active:from=2017-01-01,to=2018-01-01~ | -| ~(clocked :on -1)~ | ~clocked:on=-1~ | -| ~(heading "quoted phrase" "word")~ | ~heading:"quoted phrase",word~ | -| ~(and (tags "book" "books") (priority "A"))~ | ~tags:book,books priority:A~ | -| ~(priority >= B)~ | ~priority:A,B~ | +| Sexp syntax | Non-sexp syntax | +|-------------------------------------------------+----------------------------------------------| +| ~(todo)~ | ~todo:~ | +| ~(todo "SOMEDAY")~ | ~todo:SOMEDAY~ | +| ~(todo "SOMEDAY" "WAITING")~ | ~todo:SOMEDAY,WAITING~ | +| ~(ts :on today)~ | ~ts:on=today~ | +| ~(ts-active :from "2017-01-01" :to "2018-01-01")~ | ~ts-active:from=2017-01-01,to=2018-01-01~ | +| ~(clocked :on -1)~ | ~clocked:on=-1~ | +| ~(heading "quoted phrase" "word")~ | ~heading:"quoted phrase",word~ | +| ~(and (tags "book" "books") (priority "A"))~ | ~tags:book,books priority:A~ | +| ~(src :lang "elisp" :regexps ("defun"))~ | ~src:defun,lang=elisp~ or ~src:lang=elisp,defun~ | +| ~(priority >= B)~ | ~priority:A,B~ | Note that the =priority= predicate does not support comparators in the non-sexp syntax, so multiple priorities should be passed instead, as seen in the last example. @@ -189,7 +190,7 @@ Arguments are listed next to predicate names, where applicable. + =priority (&optional comparator-or-priority priority)= :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. + =property (property &optional value)= :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. + =regexp (&rest regexps)= :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. -+ ~src (&optional lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. ++ ~src (&key lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. + =tags (&optional tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. + =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags. - Aliases: ~inherited-tags~, ~tags-i~, ~itags~. diff --git a/org-ql.el b/org-ql.el index 4d30744..b5d898b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -591,6 +591,26 @@ Replaces bare strings with (regexp) selectors, and appropriate (setf property (substring (symbol-name property) 1))) (cons 'property (cons property value))) + ;; Source blocks. + (`(src . ,args) + ;; Rewrite to use keyword args. + (-let (regexps lang keyword-index) + (cond ((plist-get args :lang) + ;; Lang given first, or only lang given. + (setf lang (plist-get args :lang) + regexps (seq-difference args (list :lang lang)))) + ((setf keyword-index (-find-index #'keywordp args)) + ;; Regexps and lang given. + (setf lang (plist-get (cl-subseq args keyword-index) :lang) + regexps (cl-subseq args 0 keyword-index))) + (t ;; Only regexps given. + (setf regexps args))) + (when regexps + ;; This feels awkward and wrong, but we have to quote lists + ;; and avoid quoting nil. There must be a better way. + (setf regexps `(',regexps))) + `(src :lang ,lang :regexps ,@regexps))) + ;; Tags. (`(,(or 'tags-all 'tags&) . ,tags) `(and ,@(--map `(tags ,it) tags))) ;; MAYBE: -all versions for inherited and local. @@ -747,8 +767,8 @@ replace the clause with a preamble." ;; element) ;; Src blocks. - (`(src ,lang . ,_) - (setq org-ql-preamble (org-ql--format-src-block-regexp lang)) + (`(src . ,args) + (setq org-ql-preamble (org-ql--format-src-block-regexp (plist-get args :lang))) ;; Always check contents with predicate. element) @@ -795,7 +815,7 @@ replace the clause with a preamble." (rx-to-string `(seq bol (group (zero-or-more (any " "))) "#+begin_src" (one-or-more (any " ")) - ,lang + ,(or lang `(1+ (not (any " \n \f ")))) (zero-or-more (any " ")) (group (or (seq (zero-or-more (not (any "\n\":"))) "\"" @@ -1130,9 +1150,10 @@ priority B)." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) -(org-ql--defpred src (&optional lang &rest regexps) +(org-ql--defpred src (&key regexps lang) "Return non-nil if current entry contains an Org source block matching all of REGEXPS. -If LANG is non-nil, the block must be in that language." +If keyword argument LANG is non-nil, the block must be in that +language." (catch 'return (save-excursion (save-match-data diff --git a/org-ql.info b/org-ql.info index fd67821..4c5c984 100644 --- a/org-ql.info +++ b/org-ql.info @@ -329,7 +329,7 @@ default, when multiple predicates are used, they are combined with boolean and. Sexp syntax Non-sexp syntax ------------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------------------- ‘(todo)’ ‘todo:’ ‘(todo "SOMEDAY")’ ‘todo:SOMEDAY’ ‘(todo "SOMEDAY" "WAITING")’ ‘todo:SOMEDAY,WAITING’ @@ -338,6 +338,7 @@ Sexp syntax Non-sexp syntax ‘(clocked :on -1)’ ‘clocked:on=-1’ ‘(heading "quoted phrase" "word")’ ‘heading:"quoted phrase",word’ ‘(and (tags "book" "books") (priority "A"))’ ‘tags:book,books priority:A’ +‘(src :lang "elisp" :regexps ("defun"))’ ‘src:defun,lang=elisp’ or ‘src:lang=elisp,defun’ ‘(priority >= B)’ ‘priority:A,B’ Note that the priority predicate does not support comparators in the @@ -411,7 +412,7 @@ Arguments are listed next to predicate names, where applicable. Return non-nil if current entry matches all of ‘REGEXPS’ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. -‘‘src (&optional lang regexps)’’ +‘‘src (&key lang regexps)’’ Return non-nil if current entry contains an Org Babel source block. If ‘LANG’ is non-nil, match blocks of that language. If ‘REGEXPS’ is non-nil, require that block’s contents match all regexps. @@ -979,24 +980,24 @@ Node: org-ql-view-recent-items6452 Node: org-ql-sparse-tree6936 Node: Queries7736 Node: Non-sexp query syntax8578 -Node: Predicates10078 -Node: Date/time predicates15197 -Node: Functions / Macros17832 -Node: Agenda-like views18019 -Node: Listing / acting-on results19424 -Node: Changelog24026 -Node: 04-pre24548 -Node: 03125492 -Node: 0325690 -Node: 02328663 -Node: 02228889 -Node: 02129155 -Node: 0229352 -Node: 0133385 -Node: Notes33484 -Node: Comparison with Org Agenda searches33646 -Node: org-sidebar34517 -Node: License34796 +Node: Predicates10198 +Node: Date/time predicates15312 +Node: Functions / Macros17947 +Node: Agenda-like views18134 +Node: Listing / acting-on results19539 +Node: Changelog24141 +Node: 04-pre24663 +Node: 03125607 +Node: 0325805 +Node: 02328778 +Node: 02229004 +Node: 02129270 +Node: 0229467 +Node: 0133500 +Node: Notes33599 +Node: Comparison with Org Agenda searches33761 +Node: org-sidebar34632 +Node: License34911  End Tag Table From 949a06c3ab50482b749fd2d4350837a197660d96 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 9 Oct 2019 19:05:11 -0500 Subject: [PATCH 018/560] Add: Negation in plain queries --- README.org | 2 ++ org-ql.el | 12 +++++++++--- org-ql.info | 39 +++++++++++++++++++++------------------ tests/test-org-ql.el | 11 +++++++++++ 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/README.org b/README.org index c57321b..7f4022d 100644 --- a/README.org +++ b/README.org @@ -164,6 +164,7 @@ The command =org-ql-search= also accepts, and the command =helm-org-ql= only acc | ~(heading "quoted phrase" "word")~ | ~heading:"quoted phrase",word~ | | ~(and (tags "book" "books") (priority "A"))~ | ~tags:book,books priority:A~ | | ~(src :lang "elisp" :regexps ("defun"))~ | ~src:defun,lang=elisp~ or ~src:lang=elisp,defun~ | +| ~(and (tags "space") (not (regexp "moon")))~ | ~tags:space !moon~ | | ~(priority >= B)~ | ~priority:A,B~ | Note that the =priority= predicate does not support comparators in the non-sexp syntax, so multiple priorities should be passed instead, as seen in the last example. @@ -375,6 +376,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre *Added* ++ Negation of terms in plain queries using ~!~. For example, ~tags:space !moon~ to exclude entries which contain ~moon~. + Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + Info manual. + Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. diff --git a/org-ql.el b/org-ql.el index b5d898b..7c63954 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1487,10 +1487,15 @@ Builds the PEG expression using predicates defined in Multiple predicates are combined with BOOLEAN." (unless (s-blank-str? input) (let* ((query (peg-parse-string - ((query (+ (or (and predicate-with-args `(pred args -- (cons (intern pred) args))) - (and predicate-without-args `(pred -- (list (intern pred)))) - (and plain-string `(s -- (list 'regexp s)))) + ((query (+ term (opt (+ (syntax-class whitespace) (any))))) + (term (or (and negation (list positive-term) + ;; This is a bit confusing, but it seems to work. There's probably a better way. + `(pred -- (list 'not (car pred)))) + positive-term)) + (positive-term (or (and predicate-with-args `(pred args -- (cons (intern pred) args))) + (and predicate-without-args `(pred -- (list (intern pred)))) + (and plain-string `(s -- (list 'regexp s))))) (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) (predicate-with-args (substring predicate) ":" args) (predicate-without-args (substring predicate) ":") @@ -1500,6 +1505,7 @@ Multiple predicates are combined with BOOLEAN." (keyword (substring (+ (not (or separator "=" "\"" (syntax-class whitespace))) (any)))) (quoted-arg "\"" (substring (+ (not (or separator "\"")) (any))) "\"") (unquoted-arg (substring (+ (not (or separator "\"" (syntax-class whitespace))) (any)))) + (negation "!") (separator "," )) input 'noerror))) ;; Discard the t that `peg-parse-string' always returns as the first diff --git a/org-ql.info b/org-ql.info index 4c5c984..7c707b2 100644 --- a/org-ql.info +++ b/org-ql.info @@ -339,6 +339,7 @@ Sexp syntax Non-sexp syntax ‘(heading "quoted phrase" "word")’ ‘heading:"quoted phrase",word’ ‘(and (tags "book" "books") (priority "A"))’ ‘tags:book,books priority:A’ ‘(src :lang "elisp" :regexps ("defun"))’ ‘src:defun,lang=elisp’ or ‘src:lang=elisp,defun’ +‘(and (tags "space") (not (regexp "moon")))’ ‘tags:space !moon’ ‘(priority >= B)’ ‘priority:A,B’ Note that the priority predicate does not support comparators in the @@ -695,6 +696,8 @@ File: README.info, Node: 04-pre, Next: 031, Up: Changelog =========== *Added* + • Negation of terms in plain queries using ‘!’. For example, + ‘tags:space !moon’ to exclude entries which contain ‘moon’. • Predicates outline-path (alias olp) and outline-path-segment (alias olps). • Info manual. @@ -980,24 +983,24 @@ Node: org-ql-view-recent-items6452 Node: org-ql-sparse-tree6936 Node: Queries7736 Node: Non-sexp query syntax8578 -Node: Predicates10198 -Node: Date/time predicates15312 -Node: Functions / Macros17947 -Node: Agenda-like views18134 -Node: Listing / acting-on results19539 -Node: Changelog24141 -Node: 04-pre24663 -Node: 03125607 -Node: 0325805 -Node: 02328778 -Node: 02229004 -Node: 02129270 -Node: 0229467 -Node: 0133500 -Node: Notes33599 -Node: Comparison with Org Agenda searches33761 -Node: org-sidebar34632 -Node: License34911 +Node: Predicates10277 +Node: Date/time predicates15391 +Node: Functions / Macros18026 +Node: Agenda-like views18213 +Node: Listing / acting-on results19618 +Node: Changelog24220 +Node: 04-pre24742 +Node: 03125830 +Node: 0326028 +Node: 02329001 +Node: 02229227 +Node: 02129493 +Node: 0229690 +Node: 0133723 +Node: Notes33822 +Node: Comparison with Org Agenda searches33984 +Node: org-sidebar34855 +Node: License35134  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 84ebadc..24a08be 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -231,6 +231,17 @@ RESULTS should be a list of strings as returned by ;; TODO: Other predicates. + (it "Negated terms" + (expect (org-ql--plain-query "todo: !todo:CHECK,SOMEDAY") + :to-equal '(and (todo) (not (todo "CHECK" "SOMEDAY")))) + (expect (org-ql--plain-query "!todo:CHECK,SOMEDAY todo:") + :to-equal '(and (not (todo "CHECK" "SOMEDAY")) (todo))) + (expect (org-ql--plain-query "tags:universe !moon") + :to-equal '(and (tags "universe") (not (regexp "moon")))) + (expect (org-ql--plain-query "!moon tags:universe") + :to-equal '(and (not (regexp "moon")) (tags "universe"))) + (expect (org-ql--plain-query "mars !ts:on=today") + :to-equal '(and (regexp "mars") (not (ts :on "today"))))) (it "Regexp predicates" (expect (org-ql--plain-query "scheduled") ;; No colon after keyword, so not a predicate query. From be7ac9921d819cae3d1f1115b3ff284a79d3ed27 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 01:00:45 -0500 Subject: [PATCH 019/560] Meta: 0.3.2-pre --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 7d17352..cbb8137 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.3.1 +;; Version: 0.3.2-pre ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda From f2910261e2eea2f6c48b2e70b207b0f242b957cf Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 01:06:22 -0500 Subject: [PATCH 020/560] Fix: (org-ql-search) Accept symbol as arg to :super-groups --- README.org | 5 +++++ org-ql-search.el | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index f3a79b5..8f9a8b1 100644 --- a/README.org +++ b/README.org @@ -363,6 +363,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.3.2-pre + +*Fixed* ++ In =org-ql-search=, accept symbol as ~:super-groups~ argument. + ** 0.3.1 *Fixed* diff --git a/org-ql-search.el b/org-ql-search.el index 45f349a..6d96871 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -166,7 +166,9 @@ necessary." (org-ql-view-super-groups super-groups) (org-ql-view-title title)) (when super-groups - (let ((org-super-agenda-groups super-groups)) + (let ((org-super-agenda-groups (cl-etypecase super-groups + (symbol (symbol-value super-groups)) + (list super-groups)))) (setf strings (org-super-agenda--group-items strings)))) (org-ql-view--display :buffer buffer :header header :string (s-join "\n" strings)))) From 43b94dd4a819c49346737a07ca508e7684ad50b6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 01:07:15 -0500 Subject: [PATCH 021/560] Fix: (org-ql-views) Beginning/end-of-week timestamp times --- README.org | 1 + org-ql-view.el | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index 8f9a8b1..270230b 100644 --- a/README.org +++ b/README.org @@ -367,6 +367,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Fixed* + In =org-ql-search=, accept symbol as ~:super-groups~ argument. ++ In the =This week= and =Next week= default =org-ql-views= views, set timestamps for beginning-of-week to 00:00:00 and end-of-week to 23:59:59. ** 0.3.1 diff --git a/org-ql-view.el b/org-ql-view.el index d65a7a7..1519873 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -147,8 +147,13 @@ See info node `(elisp)Cyclic Window Ordering'." (cons "This week" (lambda () "Show items with an active timestamp during this calendar week." (interactive) - (let* ((beg-of-week (ts-adjust 'day (- (ts-dow (ts-now))) (ts-now))) - (end-of-week (ts-adjust 'day (- 6 (ts-dow (ts-now))) (ts-now)))) + (let* ((ts (ts-now)) + (beg-of-week (->> ts + (ts-adjust 'day (- (ts-dow (ts-now)))) + (ts-apply :hour 0 :minute 0 :second 0))) + (end-of-week (->> ts + (ts-adjust 'day (- 6 (ts-dow (ts-now)))) + (ts-apply :hour 23 :minute 59 :second 59)))) (org-ql-search (org-agenda-files) `(ts-active :from ,beg-of-week :to ,end-of-week) @@ -159,8 +164,12 @@ See info node `(elisp)Cyclic Window Ordering'." "Show items with an active timestamp during the next calendar week." (interactive) (let* ((ts (ts-adjust 'day 7 (ts-now))) - (beg-of-week (ts-adjust 'day (- (ts-dow (ts-now))) ts)) - (end-of-week (ts-adjust 'day (- 6 (ts-dow (ts-now))) ts))) + (beg-of-week (->> ts + (ts-adjust 'day (- (ts-dow (ts-now)))) + (ts-apply :hour 0 :minute 0 :second 0))) + (end-of-week (->> ts + (ts-adjust 'day (- 6 (ts-dow (ts-now)))) + (ts-apply :hour 23 :minute 59 :second 59)))) (org-ql-search (org-agenda-files) `(ts-active :from ,beg-of-week :to ,end-of-week) From 7a4a41e402ab97a9a6cc3d09f8dbb975a78b1f2b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 01:53:34 -0500 Subject: [PATCH 022/560] Fix: Quoted phrase plain-string queries --- README.org | 1 + org-ql.el | 2 +- tests/test-org-ql.el | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 270230b..f073f02 100644 --- a/README.org +++ b/README.org @@ -368,6 +368,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Fixed* + In =org-ql-search=, accept symbol as ~:super-groups~ argument. + In the =This week= and =Next week= default =org-ql-views= views, set timestamps for beginning-of-week to 00:00:00 and end-of-week to 23:59:59. ++ Plain quoted-phrases in non-sexp queries. ** 0.3.1 diff --git a/org-ql.el b/org-ql.el index cbb8137..db1d8d9 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1296,7 +1296,7 @@ Multiple predicates are combined with BOOLEAN." (and predicate-without-args `(pred -- (list (intern pred)))) (and plain-string `(s -- (list 'regexp s)))) (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (plain-string (or quoted-arg unquoted-arg)) (predicate-with-args (substring predicate) ":" args) (predicate-without-args (substring predicate) ":") (predicate (or ,@predicates)) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index c7b95bc..483b703 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -235,6 +235,8 @@ RESULTS should be a list of strings as returned by (expect (org-ql--plain-query "scheduled") ;; No colon after keyword, so not a predicate query. :to-equal '(regexp "scheduled")) + (expect (org-ql--plain-query "\"quoted phrase\"") + :to-equal '(regexp "quoted phrase")) (expect (org-ql--plain-query "regexp:word") :to-equal '(regexp "word")) (expect (org-ql--plain-query "regexp:\"quoted phrase\"") From 2274efce077c7cf8b2930a8bfb9980c251d8e737 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 01:09:05 -0500 Subject: [PATCH 023/560] Release: 0.3.2 --- README.org | 2 +- org-ql.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index f073f02..5637cc6 100644 --- a/README.org +++ b/README.org @@ -363,7 +363,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. -** 0.3.2-pre +** 0.3.2 *Fixed* + In =org-ql-search=, accept symbol as ~:super-groups~ argument. diff --git a/org-ql.el b/org-ql.el index db1d8d9..04d8974 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.3.2-pre +;; Version: 0.3.2 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda From 7d321630a064864d77a760015169c206e077be9b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 02:04:04 -0500 Subject: [PATCH 024/560] Test: Add test for negated, plain quoted phrase 0.3.2 doesn't have negation, and this should be tested with negation. --- tests/test-org-ql.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 5f1f532..9ae17a3 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -241,7 +241,9 @@ RESULTS should be a list of strings as returned by (expect (org-ql--plain-query "!moon tags:universe") :to-equal '(and (not (regexp "moon")) (tags "universe"))) (expect (org-ql--plain-query "mars !ts:on=today") - :to-equal '(and (regexp "mars") (not (ts :on "today"))))) + :to-equal '(and (regexp "mars") (not (ts :on "today")))) + (expect (org-ql--plain-query "!\"quoted phrase\"") + :to-equal '(not (regexp "quoted phrase")))) (it "Regexp predicates" (expect (org-ql--plain-query "scheduled") ;; No colon after keyword, so not a predicate query. From 0d6523f85b48080582a84b1dc1213f80de40d3c6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 19 Oct 2019 02:10:04 -0500 Subject: [PATCH 025/560] Add: (heading) Alias "h" --- README.org | 2 ++ org-ql.el | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index e3f0171..a093f5b 100644 --- a/README.org +++ b/README.org @@ -182,6 +182,7 @@ Arguments are listed next to predicate names, where applicable. + =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + =habit= :: Return non-nil if entry is a habit. + =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). + - Aliases: =h=. + =level (level-or-comparator &optional level)= :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. + =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of ~STRINGS~. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~. - Aliases: ~olp~. @@ -384,6 +385,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. + Command ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. + Predicate ~src~, which matches Org Babel source blocks. ++ Alias =h= for =heading= predicate. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql.el b/org-ql.el index a7a0336..3d64772 100644 --- a/org-ql.el +++ b/org-ql.el @@ -569,6 +569,11 @@ Replaces bare strings with (regexp) selectors, and appropriate (ts-apply :hour 23 :minute 59 :second 59)))) `(,pred :to ,to))) + ;; Headings. + (`(h . ,args) + ;; "h" alias. + `(heading ,@args)) + ;; Outline paths. (`(,(or 'outline-path 'olp) . ,strings) ;; Regexp quote headings. @@ -1132,7 +1137,7 @@ priority B)." always (save-excursion (re-search-forward regexp end t)))))) -(org-ql--defpred heading (&rest regexps) +(org-ql--defpred (heading h) (&rest regexps) "Return non-nil if current entry's heading matches all REGEXPS (regexp strings)." ;; TODO: In Org 9.2+, `org-get-heading' takes 2 more arguments. (let ((heading (org-get-heading 'no-tags 'no-todo))) From cb6509ca6a837d55937be23194b092e51bccc88e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 28 Oct 2019 08:29:06 -0500 Subject: [PATCH 026/560] Notes: Add mailing list post by John Kitchin --- notes.org | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/notes.org b/notes.org index a52cf2b..a033215 100644 --- a/notes.org +++ b/notes.org @@ -882,6 +882,37 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled * References ** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] + +** [[gnus:gmane.emacs.orgmode#CAJ51EToLCm5zDLKu8XeuqEWrLhHZF+OoNkviPSivZbFttzF8=A@mail.gmail.com][John Kitchin on rewriting the Org agenda code]] :Emacs:Org: + +[2019-10-28 Mon 08:28] Originally from [[id:90a68535-2403-4ba9-a117-60be1862628f][this entry in my notes]]. + +#+BEGIN_QUOTE +From: John Kitchin +Subject: Re: [Orgmode] Slow speed of week and month views +Newsgroups: gmane.emacs.orgmode +To: Karl Voit +Cc: "emacs-orgmode@gnu.org" +Date: Sat, 5 Aug 2017 18:17:09 -0400 (4 hours, 11 minutes, 38 seconds ago) + +I can think of two possibilities for a future approach (besides a deep dive on profiling the current elisp to improve the speed there). They both involve some substantial coding though, and would probably add dependencies. I am curious what anyone things about these, or if there are other ideas. + +One is to use the new dynamic module capability to write an org parser in C, or a dedicated agenda function, which would presumably be faster than in elisp. This seems hard, and for me would certainly be a multiyear project I am sure! The downside of this is the need to compile the module. I don't know how easy it would be to make this work across platforms with the relatively easy install org-mode currently has. This could have a side benefit though of a c-lib that could be used by others to expand where org-mode is used. + +The other way that might work is to rely more heavily on a cached version of the files, perhaps in a different format than elisp, that is faster to work with. The approach I have explored in this is to index org files into a sqlite database. The idea then would be to generate the agenda from a sql query. I use something like this already to "find stuff in orgmode anywhere". One of the reasons I wrote this is the org-agenda list of files isn't practical for me because my files are so scattered on my file system. I had a need to be able to find TODOs in research projects in a pretty wide range of locations. + +The code I use is at https://github.com/jkitchin/scimax/blob/master/org-db.el, and from one database I can find headlines, contacts, locations, TODO headlines across my file system, all the files that contain a particular link, and my own recent org files. This approach relies on emacsql, and a set of hook functions to update the database whenever a file is changed. It is not robust, e.g. the file could be out of sync with the db if it is modified outside emacs, but this works well enough for me so far. Updated files get reindexed whenever emacs is idle. It was a compromise on walking the file system all the time or daily, or trying to use inotify and you can always run a command to prune/sync all the files any time you want. + +sqlite is ok, but with emacsql you cannot put strings in it directly (at least when I wrote the org-db code), which has limited it for full-text search so far. Also with text, the db got up to about 0.5 GB in size, and started slowing down. So it doesn't have text in it for now. It has all the other limitations of sqlite too, limited support for locking, single process.... + +I am moderately motivated to switch from sqlite to MongoDB, but the support for Mongo in emacs is pretty crummy (I tried writing a few traditional interfaces, but the performance was not that good, and limited since Mongo uses bson, and it is just not the same as json!). Why Mongo? Mostly because the Mongo query language is basically json and easy to generate in Emacs, unlike sql. Also, it is flexible and easy to adapt to new things, e.g. indexing src-blocks or tables or whatever org-element you want. (And I want to use Mongo for something else too ;). Obviously these all add dependencies, and might not be suitable for the core org-mode distribution. But I do think it is important to think about ways to scale org-mode while maintaining compatibility with the core. + +The main point of the database was to get a query language, persistence and good performance. I have also used caches to speed up using bibtex files, and my org-contacts with reasonable performance. These have been all elisp, with no additional dependencies. Maybe one could do something similar to keep an agenda cache that is persistent and updated via hook functions. + +Thoughts? + +John +#+END_QUOTE :PROPERTIES: :archive.is: http://archive.is/33R9M :END: From d3272cdd8bd013d6925696656f5ed51a4a5e0c4b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 5 Nov 2019 15:40:05 -0600 Subject: [PATCH 027/560] Add: (view--display) Insert newline at end of buffer Prevents end-of-buffer from scrolling the window horizontally. Fixes #50. Thanks to @xeijin for suggesting. --- README.org | 1 + org-ql-view.el | 2 +- org-ql.info | 102 +++++++++++++++++++++++++++++-------------------- 3 files changed, 63 insertions(+), 42 deletions(-) diff --git a/README.org b/README.org index a093f5b..75fd7b0 100644 --- a/README.org +++ b/README.org @@ -386,6 +386,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Command ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. + Predicate ~src~, which matches Org Babel source blocks. + Alias =h= for =heading= predicate. ++ Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql-view.el b/org-ql-view.el index c17948e..e7f0329 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -378,7 +378,7 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', ;; Clear buffer, insert entries, etc. (let ((inhibit-read-only t)) (erase-buffer) - (insert string) + (insert string "\n") (pop-to-buffer (current-buffer) org-ql-view-display-buffer-action) (org-agenda-finalize) (goto-char (point-min)))))) diff --git a/org-ql.info b/org-ql.info index 7c707b2..55e49ce 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog * 0.4-pre: 04-pre. +* 0.3.2: 032. * 0.3.1: 031. * 0.3: 03. * 0.2.3: 023. @@ -372,6 +373,7 @@ Arguments are listed next to predicate names, where applicable. ‘heading (&rest regexps)’ Return non-nil if current entry’s heading matches all ‘REGEXPS’ (regexp strings). + • Aliases: h. ‘level (level-or-comparator &optional level)’ Return non-nil if current heading’s outline level matches arguments. The following forms are accepted: ‘(level NUMBER)’: @@ -681,6 +683,7 @@ releases. * Menu: * 0.4-pre: 04-pre. +* 0.3.2: 032. * 0.3.1: 031. * 0.3: 03. * 0.2.3: 023. @@ -690,7 +693,7 @@ releases. * 0.1: 01.  -File: README.info, Node: 04-pre, Next: 031, Up: Changelog +File: README.info, Node: 04-pre, Next: 032, Up: Changelog 5.1 0.4-pre =========== @@ -711,15 +714,31 @@ File: README.info, Node: 04-pre, Next: 031, Up: Changelog • Command ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ selected with Helm. • Predicate ‘src’, which matches Org Babel source blocks. + • Alias h for heading predicate. + • Search/view buffers now always end with a newline, which prevents + side-scrolling of the window when calling end-of-buffer. *Internal* • Added generic node data cache to speed up recursive, tree-based queries.  -File: README.info, Node: 031, Next: 03, Prev: 04-pre, Up: Changelog +File: README.info, Node: 032, Next: 031, Prev: 04-pre, Up: Changelog -5.2 0.3.1 +5.2 0.3.2 +========= + +*Fixed* + • In org-ql-search, accept symbol as ‘:super-groups’ argument. + • In the This week and Next week default org-ql-views views, set + timestamps for beginning-of-week to 00:00:00 and end-of-week to + 23:59:59. + • Plain quoted-phrases in non-sexp queries. + + +File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog + +5.3 0.3.1 ========= *Fixed* @@ -729,7 +748,7 @@ File: README.info, Node: 031, Next: 03, Prev: 04-pre, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.3 0.3 +5.4 0.3 ======= *Added* @@ -794,7 +813,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.4 0.2.3 +5.5 0.2.3 ========= *Fixed* @@ -804,7 +823,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.5 0.2.2 +5.6 0.2.2 ========= *Fixed* @@ -815,7 +834,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.6 0.2.1 +5.7 0.2.1 ========= *Fixed* @@ -825,7 +844,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.7 0.2 +5.8 0.2 ======= *Added* @@ -908,7 +927,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.8 0.1 +5.9 0.1 ======= First tagged release. @@ -969,38 +988,39 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1352 -Node: Screenshots1500 -Node: Installation1618 -Node: Quelpa2256 -Node: Usage2699 -Node: Commands3609 -Node: org-ql-search3838 -Node: helm-org-ql5486 -Node: org-ql-view5898 -Node: org-ql-view-sidebar6096 -Node: org-ql-view-recent-items6452 -Node: org-ql-sparse-tree6936 -Node: Queries7736 -Node: Non-sexp query syntax8578 -Node: Predicates10277 -Node: Date/time predicates15391 -Node: Functions / Macros18026 -Node: Agenda-like views18213 -Node: Listing / acting-on results19618 -Node: Changelog24220 -Node: 04-pre24742 -Node: 03125830 -Node: 0326028 -Node: 02329001 -Node: 02229227 -Node: 02129493 -Node: 0229690 -Node: 0133723 -Node: Notes33822 -Node: Comparison with Org Agenda searches33984 -Node: org-sidebar34855 -Node: License35134 +Node: Contents1367 +Node: Screenshots1515 +Node: Installation1633 +Node: Quelpa2271 +Node: Usage2714 +Node: Commands3624 +Node: org-ql-search3853 +Node: helm-org-ql5501 +Node: org-ql-view5913 +Node: org-ql-view-sidebar6111 +Node: org-ql-view-recent-items6467 +Node: org-ql-sparse-tree6951 +Node: Queries7751 +Node: Non-sexp query syntax8593 +Node: Predicates10292 +Node: Date/time predicates15430 +Node: Functions / Macros18065 +Node: Agenda-like views18252 +Node: Listing / acting-on results19657 +Node: Changelog24259 +Node: 04-pre24796 +Node: 03226057 +Node: 03126438 +Node: 0326633 +Node: 02329606 +Node: 02229832 +Node: 02130098 +Node: 0230295 +Node: 0134328 +Node: Notes34427 +Node: Comparison with Org Agenda searches34589 +Node: org-sidebar35460 +Node: License35739  End Tag Table From 02159a831ab10cad3c6e04a6951697e28d5ee8cd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 24 Nov 2019 05:25:38 -0600 Subject: [PATCH 028/560] Notes: Add/update --- notes.org | 314 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 195 insertions(+), 119 deletions(-) diff --git a/notes.org b/notes.org index a033215..4891e34 100644 --- a/notes.org +++ b/notes.org @@ -6,125 +6,6 @@ Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. -** TODO [#A] Helm command - -In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. - -*** TODO Add - -*** TODO Demonstrate - -*** UNDERWAY Parsing non-Lisp queries - -[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror)) - ((predicate . args) (nreverse parsed))) - (when predicate - (list :predicate predicate :args args :combinator combinator))) - ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) -#+END_SRC - -I don't know where the =t= is coming from. - -The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (syntax-class whitespace)))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) -#+END_SRC - -In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. - -This seems to work, but we'll have to parse the args again in a separate step: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) -#+END_SRC - -Well, a bit of fiddling (lots of trial-and-error required) produced this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) -#+END_SRC - -That seems pretty usable! - ** TODO [#A] Outline path in buffers-files arg :PROPERTIES: :ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 @@ -225,6 +106,82 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or (org-ql-agenda--agenda nil nil :strings strings))) #+END_SRC +Another, more up-to-date implementation: + +#+BEGIN_SRC elisp + ;; NOTE: ts structs don't (sometimes? or always?) compare properly + ;; with default hash tables, e.g. this code: + + ;; (let* ((ts-a #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572670800.0)) + ;; (ts-b #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572584400.0))) + ;; (list :equal (equal ts-a ts-b) + ;; :sxhash-equal (equal (sxhash ts-a) (sxhash ts-b)))) ;;=> (:equal nil :sxhash-equal t) + + ;; So we must use the "contents-hash" table as described in the Elisp manual. + (define-hash-table-test 'contents-hash 'equal 'sxhash-equal) + + (cl-defun org-ql-view-timeline (buffers-files &key from to on) + "FIXME: DOcstring" + (cl-flet ((parse-ts-arg + (arg type) + ;; Parse ARG as a string or TS struct and adjust it to the beginning + ;; or end of its day, depending on whether TYPE is `:begin' or `:end'. + (-let (((hour minute second) (cl-ecase type + (:begin '(0 0 0)) + (:end '(23 59 59))))) + (->> (cl-typecase arg + (string (ts-parse arg)) + (ts arg)) + (ts-apply :hour hour :minute minute :second second))))) + (let* ((ts-predicate `(lambda (ts) + ,(cond (on `(ts-in ,(parse-ts-arg on :begin) + ts + ,(parse-ts-arg on :end))) + ((and from to) `(ts-in ,(parse-ts-arg from :begin) + ts + ,(parse-ts-arg to :end))) + (from `(ts<= ,(parse-ts-arg from :begin) ts)) + (to `(ts<= ts ,(parse-ts-arg to :end))) + (t (user-error "Huh?"))))) + (query (cond (on `(ts :from ,(parse-ts-arg on :begin) + :to ,(parse-ts-arg on :end))) + (t (append (list 'ts) + (when from + `(:from ,(parse-ts-arg from :begin))) + (when to + `(:to ,(parse-ts-arg to :end))))))) + (date-ts-table (make-hash-table :test 'contents-hash)) + (_results (org-ql-select buffers-files query + :action (lambda () + (let* ((string (->> (org-element-headline-parser + (line-end-position)) + org-ql--add-markers + org-ql-view--format-element))) + (cl-loop with limit = (org-entry-end-position) + while (re-search-forward org-ts-regexp-both limit t) + for ts = (->> (match-string 0) ts-parse-org) + when (funcall ts-predicate ts) + do (cl-pushnew (cons ts (concat (ts-format " %H:%M" ts) + string)) + (gethash (ts-apply :hour 0 :minute 0 :second 0 ts) + date-ts-table) + :test #'equal)))))) + (date-tss-sorted (->> date-ts-table hash-table-keys (-sort #'ts<))) + (string (cl-loop for date-ts in date-tss-sorted + for date-string = (propertize (ts-format "%Y-%m-%d" date-ts) + 'face 'org-agenda-structure) + concat (concat "\n" date-string) + concat (cl-loop for (ts . entry) in (->> (gethash date-ts date-ts-table) + (-sort (-on #'ts< #'car))) + concat (concat "\n" entry))))) + (org-ql-view--display :buffer "Timeline" + :header "Timeline" + :string string)))) + + ;; Used like: + ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") +#+END_SRC + ** TODO [#B] Add more sorters? + [ ] =category= @@ -641,6 +598,125 @@ This works okay (except the priority accessor needs to be fixed, because Org pri When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** DONE [#A] Helm command + +In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. + +*** DONE Add + +*** DONE Demonstrate + +*** DONE Parsing non-Lisp queries + +[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror)) + ((predicate . args) (nreverse parsed))) + (when predicate + (list :predicate predicate :args args :combinator combinator))) + ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) +#+END_SRC + +I don't know where the =t= is coming from. + +The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (syntax-class whitespace)))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) +#+END_SRC + +In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. + +This seems to work, but we'll have to parse the args again in a separate step: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) +#+END_SRC + +Well, a bit of fiddling (lots of trial-and-error required) produced this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) +#+END_SRC + +That seems pretty usable! + ** DONE Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] :LOGBOOK: From a1851ed0eb6587e822b62d18a884c1eabb1411c1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 24 Nov 2019 05:43:21 -0600 Subject: [PATCH 029/560] Fix: (--value-at) Clear value cache when buffer changes Fixes #59. Thanks to Daniel Hubmann (@hubisan) for reporting. --- org-ql.el | 3 ++- tests/test-org-ql.el | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 3d64772..7e15cc0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -470,7 +470,8 @@ Values compared with `equal'." buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) (unless (and buffer-cache buffer-unmodified-p) ;; Buffer-local node cache empty or invalid: make new one. - (setf position-cache (make-hash-table)) + (setf position-cache (make-hash-table) + value-cache (gethash position position-cache)) (puthash (current-buffer) (cons (buffer-modified-tick) position-cache) org-ql-node-value-cache)) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 9ae17a3..ea6ab8a 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -142,6 +142,25 @@ RESULTS should be a list of strings as returned by (cl-loop while (re-search-forward org-heading-regexp nil t) sum 1))))) + (describe "Caching" + (it "Clears value cache after buffer changes" + ;; See . + (with-temp-buffer + (org-mode) + (insert "* Heading 1 +* Heading 2") + ;; FIXME: `--value-at' does not actually move point, so we do it here. + (goto-char (point-min)) + (expect (org-ql--value-at (point-min) #'org-get-heading) + :to-equal "Heading 1") + (erase-buffer) + ;; FIXME: See above. + (insert "* Heading 2") + (goto-char (point-min)) + (org-ql--value-at (point-min) #'point) + (expect (org-ql--value-at (point-min) #'org-get-heading) + :to-equal "Heading 2")))) + (describe "Query functions/macros" (it "org-ql" From d3a73732ac11edbaff20a77903acc06b6634568b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 28 Nov 2019 15:09:43 -0600 Subject: [PATCH 030/560] Notes: Tidy --- notes.org | 8 -------- 1 file changed, 8 deletions(-) diff --git a/notes.org b/notes.org index 4891e34..ba8a203 100644 --- a/notes.org +++ b/notes.org @@ -447,14 +447,6 @@ To implement this with good performance probably needs an outline-path cache. I [2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. -** UNDERWAY [#A] Helm command - -In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. - -*** TODO Add - -*** TODO Demonstrate - ** UNDERWAY [#B] Implement view with tabulated-list-mode or magit-section [2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. From d7fe019d6ac212da50916f51f642fdf3de24d2d8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 29 Nov 2019 21:08:22 -0600 Subject: [PATCH 031/560] Fix: (helm-source-org-ql-views) Call helm-make-source directly Avoids macro expansion issues if Helm is not yet loaded. Fixes #60. Thanks to @matthuszagh for reporting. --- README.org | 3 +++ helm-org-ql.el | 2 +- org-ql.info | 31 +++++++++++++++++++------------ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 75fd7b0..e7d6331 100644 --- a/README.org +++ b/README.org @@ -388,6 +388,9 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Alias =h= for =heading= predicate. + Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. +*Fixed* ++ Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to Matt Huszagh ([[https://github.com/matthuszagh][@matthuszagh]]) for reporting.) + *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/helm-org-ql.el b/helm-org-ql.el index 26beab9..8bb886a 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -67,7 +67,7 @@ Based on `helm-map'.") (defvar helm-source-org-ql-views - (helm-build-sync-source "Org QL Views" + (helm-make-source "Org QL Views" 'helm-source-sync :candidates (lambda () (->> org-ql-views (-map #'car) diff --git a/org-ql.info b/org-ql.info index 55e49ce..e132bd2 100644 --- a/org-ql.info +++ b/org-ql.info @@ -718,6 +718,13 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog • Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling end-of-buffer. + *Fixed* + • Call helm-make-source directly instead of using + helm-build-sync-source macro. (Fixes #60 + (https://github.com/alphapapa/org-ql/issues/60). Thanks to Matt + Huszagh (@matthuszagh (https://github.com/matthuszagh)) for + reporting.) + *Internal* • Added generic node data cache to speed up recursive, tree-based queries. @@ -1009,18 +1016,18 @@ Node: Agenda-like views18252 Node: Listing / acting-on results19657 Node: Changelog24259 Node: 04-pre24796 -Node: 03226057 -Node: 03126438 -Node: 0326633 -Node: 02329606 -Node: 02229832 -Node: 02130098 -Node: 0230295 -Node: 0134328 -Node: Notes34427 -Node: Comparison with Org Agenda searches34589 -Node: org-sidebar35460 -Node: License35739 +Node: 03226323 +Node: 03126704 +Node: 0326899 +Node: 02329872 +Node: 02230098 +Node: 02130364 +Node: 0230561 +Node: 0134594 +Node: Notes34693 +Node: Comparison with Org Agenda searches34855 +Node: org-sidebar35726 +Node: License36005  End Tag Table From cb84615d89e59b9b594833f79c99206b698521eb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Dec 2019 20:21:34 -0600 Subject: [PATCH 032/560] Tidy: helm-org-ql --- helm-org-ql.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index 8bb886a..821ea62 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -187,7 +187,7 @@ Is transformed into this query: "Return Helm source named NAME that searches BUFFERS-FILES with `helm-org-ql'." ;; Expansion of `helm-build-sync-source' macro. (helm-make-source name 'helm-source-sync - :candidates (lambda nil + :candidates (lambda () (let* ((query (org-ql--plain-query helm-pattern)) (window-width (window-width (helm-window)))) (when query @@ -208,7 +208,7 @@ Is transformed into this query: ;; where byte-compilation is actually done, but it might not be a good idea ;; to always ignore such errors/warnings. (org-ql-select buffers-files query - :action (list 'helm-org-ql--heading window-width)))))) + :action `(helm-org-ql--heading ,window-width)))))) :match #'identity :fuzzy-match nil :multimatch nil @@ -228,9 +228,9 @@ WINDOW-WIDTH should be the width of the Helm window." ;; call a setup function in a buffer before running queries. (let* ((prefix (concat (buffer-name) ":")) (width (- window-width (length prefix))) - (path (org-split-string (org-format-outline-path (org-get-outline-path) - width nil "") - "")) + (path (-> (org-get-outline-path) + (org-format-outline-path width nil "") + (org-split-string ""))) (heading (org-get-heading t)) (path (if helm-org-ql-reverse-paths (concat heading "\\" (s-join "\\" (nreverse path))) From 70a1acde938f3ce3fcac924f1ec0786bd13a83e4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 6 Dec 2019 22:07:11 -0600 Subject: [PATCH 033/560] Docs: Tidy changelog for 0.4.0-pre --- README.org | 20 +++++++++--------- org-ql.info | 58 +++++++++++++++++++++++++++-------------------------- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/README.org b/README.org index e7d6331..e137b66 100644 --- a/README.org +++ b/README.org @@ -377,19 +377,21 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre *Added* -+ Negation of terms in plain queries using ~!~. For example, ~tags:space !moon~ to exclude entries which contain ~moon~. -+ Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). ++ *Commands* + - ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. + - ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. + - ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. ++ *Queries* + - Negation of terms in plain queries using ~!~. For example, ~tags:space !moon~ to exclude entries which contain ~moon~. + - Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). + - Predicate ~src~, which matches Org Babel source blocks. + - Alias =h= for =heading= predicate. + Info manual. -+ Command ~org-ql-search~ can search files in ~org-directory~; customization options are available in the ~org-ql-search~ group. -+ Command ~org-ql-view-refresh~ can be called with a prefix argument to adjust search parameters. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. -+ Command ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. -+ Predicate ~src~, which matches Org Babel source blocks. -+ Alias =h= for =heading= predicate. -+ Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. *Fixed* -+ Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to Matt Huszagh ([[https://github.com/matthuszagh][@matthuszagh]]) for reporting.) ++ Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to [[https://github.com/matthuszagh][Matt Huszagh]] for reporting.) ++ Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql.info b/org-ql.info index e132bd2..29e105d 100644 --- a/org-ql.info +++ b/org-ql.info @@ -699,31 +699,33 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog =========== *Added* - • Negation of terms in plain queries using ‘!’. For example, - ‘tags:space !moon’ to exclude entries which contain ‘moon’. - • Predicates outline-path (alias olp) and outline-path-segment (alias - olps). + • *Commands* + • ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ + selected with Helm. + • ‘org-ql-search’ can search files in ‘org-directory’; + customization options are available in the ‘org-ql-search’ + group. + • ‘org-ql-view-refresh’ can be called with a prefix argument to + adjust search parameters. + • *Queries* + • Negation of terms in plain queries using ‘!’. For example, + ‘tags:space !moon’ to exclude entries which contain ‘moon’. + • Predicates outline-path (alias olp) and outline-path-segment + (alias olps). + • Predicate ‘src’, which matches Org Babel source blocks. + • Alias h for heading predicate. • Info manual. - • Command ‘org-ql-search’ can search files in ‘org-directory’; - customization options are available in the ‘org-ql-search’ group. - • Command ‘org-ql-view-refresh’ can be called with a prefix argument - to adjust search parameters. • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used for custom Helm commands that search certain files. - • Command ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ - selected with Helm. - • Predicate ‘src’, which matches Org Babel source blocks. - • Alias h for heading predicate. - • Search/view buffers now always end with a newline, which prevents - side-scrolling of the window when calling end-of-buffer. *Fixed* • Call helm-make-source directly instead of using helm-build-sync-source macro. (Fixes #60 (https://github.com/alphapapa/org-ql/issues/60). Thanks to Matt - Huszagh (@matthuszagh (https://github.com/matthuszagh)) for - reporting.) + Huszagh (https://github.com/matthuszagh) for reporting.) + • Search/view buffers now always end with a newline, which prevents + side-scrolling of the window when calling end-of-buffer. *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -1016,18 +1018,18 @@ Node: Agenda-like views18252 Node: Listing / acting-on results19657 Node: Changelog24259 Node: 04-pre24796 -Node: 03226323 -Node: 03126704 -Node: 0326899 -Node: 02329872 -Node: 02230098 -Node: 02130364 -Node: 0230561 -Node: 0134594 -Node: Notes34693 -Node: Comparison with Org Agenda searches34855 -Node: org-sidebar35726 -Node: License36005 +Node: 03226384 +Node: 03126765 +Node: 0326960 +Node: 02329933 +Node: 02230159 +Node: 02130425 +Node: 0230622 +Node: 0134655 +Node: Notes34754 +Node: Comparison with Org Agenda searches34916 +Node: org-sidebar35787 +Node: License36066  End Tag Table From b9dfd7d93b1b64ddd0158290c5b6bb482dc558f3 Mon Sep 17 00:00:00 2001 From: Feng Shu Date: Sun, 8 Dec 2019 13:58:47 +0800 Subject: [PATCH 034/560] Add: (regexp) Alias "r" Thanks to Feng Shu (@tumashu). --- README.org | 2 ++ org-ql.el | 7 ++++++- org-ql.info | 39 +++++++++++++++++++++------------------ 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/README.org b/README.org index e137b66..0235712 100644 --- a/README.org +++ b/README.org @@ -192,6 +192,7 @@ Arguments are listed next to predicate names, where applicable. + =priority (&optional comparator-or-priority priority)= :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. + =property (property &optional value)= :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. + =regexp (&rest regexps)= :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. + - Aliases: =r=. + ~src (&key lang regexps)~ :: Return non-nil if current entry contains an Org Babel source block. If ~LANG~ is non-nil, match blocks of that language. If ~REGEXPS~ is non-nil, require that block's contents match all regexps. + =tags (&optional tags)= :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). Tests both inherited and local tags. + =tags-inherited (&optional tags)= :: Return non-nil if current heading's inherited tags include one or more of ~TAGS~ (a list of strings). If ~TAGS~ is nil, return non-nil if heading has any inherited tags. @@ -386,6 +387,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience - Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). - Predicate ~src~, which matches Org Babel source blocks. - Alias =h= for =heading= predicate. + - Alias =r= for =regexp= predicate. (Thanks to [[https://github.com/tumashu][Feng Shu]].) + Info manual. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. diff --git a/org-ql.el b/org-ql.el index 7e15cc0..1f39d3f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -575,6 +575,11 @@ Replaces bare strings with (regexp) selectors, and appropriate ;; "h" alias. `(heading ,@args)) + ;; Regexps. + (`(r . ,args) + ;; "r" alias. + `(regexp ,@args)) + ;; Outline paths. (`(,(or 'outline-path 'olp) . ,strings) ;; Regexp quote headings. @@ -1127,7 +1132,7 @@ priority B)." "Return non-nil if entry is a habit." (org-is-habit-p)) -(org-ql--defpred regexp (&rest regexps) +(org-ql--defpred (regexp r) (&rest regexps) "Return non-nil if current entry matches all of REGEXPS (regexp strings)." (let ((end (or (save-excursion (outline-next-heading)) diff --git a/org-ql.info b/org-ql.info index 29e105d..329057f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -415,6 +415,7 @@ Arguments are listed next to predicate names, where applicable. Return non-nil if current entry matches all of ‘REGEXPS’ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. + • Aliases: r. ‘‘src (&key lang regexps)’’ Return non-nil if current entry contains an Org Babel source block. If ‘LANG’ is non-nil, match blocks of that language. If ‘REGEXPS’ @@ -714,6 +715,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog (alias olps). • Predicate ‘src’, which matches Org Babel source blocks. • Alias h for heading predicate. + • Alias r for regexp predicate. (Thanks to Feng Shu + (https://github.com/tumashu).) • Info manual. • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used @@ -1012,24 +1015,24 @@ Node: org-ql-sparse-tree6951 Node: Queries7751 Node: Non-sexp query syntax8593 Node: Predicates10292 -Node: Date/time predicates15430 -Node: Functions / Macros18065 -Node: Agenda-like views18252 -Node: Listing / acting-on results19657 -Node: Changelog24259 -Node: 04-pre24796 -Node: 03226384 -Node: 03126765 -Node: 0326960 -Node: 02329933 -Node: 02230159 -Node: 02130425 -Node: 0230622 -Node: 0134655 -Node: Notes34754 -Node: Comparison with Org Agenda searches34916 -Node: org-sidebar35787 -Node: License36066 +Node: Date/time predicates15454 +Node: Functions / Macros18089 +Node: Agenda-like views18276 +Node: Listing / acting-on results19681 +Node: Changelog24283 +Node: 04-pre24820 +Node: 03226512 +Node: 03126893 +Node: 0327088 +Node: 02330061 +Node: 02230287 +Node: 02130553 +Node: 0230750 +Node: 0134783 +Node: Notes34882 +Node: Comparison with Org Agenda searches35044 +Node: org-sidebar35915 +Node: License36194  End Tag Table From 091a732a8876b4a4bf2d18cc5b19d196a2571149 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 21 Dec 2019 16:28:51 -0600 Subject: [PATCH 035/560] Fix: (--value-at) On cache miss, return nil when function does Previously, on a cache miss, if FN returned nil, the sentinel would be returned instead of nil. Closes #78. Thanks to Josh Moller-Mara (@mm--) for reporting. --- org-ql.el | 63 ++++++++++++++++++++++---------------------- tests/test-org-ql.el | 13 ++++++++- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/org-ql.el b/org-ql.el index 1f39d3f..22e3708 100644 --- a/org-ql.el +++ b/org-ql.el @@ -447,37 +447,38 @@ Values compared with `equal'." ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables ;; bound in the else clause, so destructured variables that are non-nil, ;; like found caches, are not available in the else clause. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-node-value-cache)) - (modified-tick (car buffer-cache)) - (position-cache (cdr buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (value-cache (gethash position position-cache)) - (cached-value (alist-get fn value-cache nil nil #'equal))) - ;; Found in cache: return it. - (pcase cached-value - ('org-ql-nil nil) - (_ cached-value)) - ;; Not found in cache: get value and cache it. - (let ((new-value (or (funcall fn) 'org-ql-nil))) - ;; Check caches again, because it may have been set now, e.g. by - ;; recursively going up an outline tree. - ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? - (setf buffer-cache (gethash (current-buffer) org-ql-node-value-cache) - modified-tick (car buffer-cache) - position-cache (cdr buffer-cache) - value-cache (when position-cache - (gethash position position-cache)) - buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (unless (and buffer-cache buffer-unmodified-p) - ;; Buffer-local node cache empty or invalid: make new one. - (setf position-cache (make-hash-table) - value-cache (gethash position position-cache)) - (puthash (current-buffer) - (cons (buffer-modified-tick) position-cache) - org-ql-node-value-cache)) - (map-put value-cache fn new-value) - (puthash position value-cache position-cache) - new-value))) + (pcase (if-let* ((buffer-cache (gethash (current-buffer) org-ql-node-value-cache)) + (modified-tick (car buffer-cache)) + (position-cache (cdr buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (value-cache (gethash position position-cache)) + (cached-value (alist-get fn value-cache nil nil #'equal))) + ;; Found in cache: return it. + cached-value + ;; Not found in cache: call FN, cache and return its value. + (let ((new-value (or (funcall fn) 'org-ql-nil))) + ;; Check caches again, because it may have been set now, e.g. by + ;; recursively going up an outline tree. + ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? + (setf buffer-cache (gethash (current-buffer) org-ql-node-value-cache) + modified-tick (car buffer-cache) + position-cache (cdr buffer-cache) + value-cache (when position-cache + (gethash position position-cache)) + buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (unless (and buffer-cache buffer-unmodified-p) + ;; Buffer-local node cache empty or invalid: make new one. + (setf position-cache (make-hash-table) + value-cache (gethash position position-cache)) + (puthash (current-buffer) + (cons (buffer-modified-tick) position-cache) + org-ql-node-value-cache)) + (map-put value-cache fn new-value) + (puthash position value-cache position-cache) + new-value)) + ;; Return nil or the non-nil value. + ('org-ql-nil nil) + (else else))) (defun org-ql--add-markers (element) "Return ELEMENT with Org marker text properties added. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index ea6ab8a..60a2cb1 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -143,6 +143,7 @@ RESULTS should be a list of strings as returned by sum 1))))) (describe "Caching" + (it "Clears value cache after buffer changes" ;; See . (with-temp-buffer @@ -159,7 +160,17 @@ RESULTS should be a list of strings as returned by (goto-char (point-min)) (org-ql--value-at (point-min) #'point) (expect (org-ql--value-at (point-min) #'org-get-heading) - :to-equal "Heading 2")))) + :to-equal "Heading 2"))) + + (it "Returns nil when cache misses and function returns nil" + ;; See . + (with-temp-buffer + (org-mode) + (insert "* Heading 1") + ;; FIXME: `--value-at' does not actually move point, so we do it here. + (goto-char (point-min)) + (expect (org-ql--value-at (point-min) #'org-get-local-tags) + :to-be nil)))) (describe "Query functions/macros" From c238ebcc97ee1b47c46833dd06332f22dd43bc9a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 29 Dec 2019 17:37:15 -0600 Subject: [PATCH 036/560] Add: org-ql-view--format-query Used to e.g. make timestamp objects in query human readable for display in view headers. --- org-ql-view.el | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index e7f0329..0309a91 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -43,6 +43,7 @@ (require 's) (require 'org-super-agenda) (require 'ov) +(require 'ts) ;;;; Compatibility @@ -389,10 +390,10 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', (concat (propertize "View:" 'face 'org-agenda-structure) title " ") "")) - (query-formatted (format "%S" query)) - (query-formatted (propertize (org-ql-view--font-lock-string 'emacs-lisp-mode query-formatted) - 'help-echo query-formatted)) + (query-formatted (org-ql-view--format-query query)) (query-width (length query-formatted)) + (query-propertized (propertize (org-ql-view--font-lock-string 'emacs-lisp-mode query-formatted) + 'help-echo query-formatted)) (available-width (max 0 (- (window-width) (length "In: ") (length "Query: ") @@ -404,10 +405,22 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', 'help-echo buffers-files-formatted))) (concat title (propertize "Query:" 'face 'org-agenda-structure) - query-formatted " " + query-propertized " " (propertize "In:" 'face 'org-agenda-structure) buffers-files-formatted))) +(defun org-ql-view--format-query (query) + "Return QUERY formatted as a string. +Makes QUERY more readable, e.g. timestamp objects are replaced +with human-readable strings." + (cl-labels ((rec (form) + (cl-typecase form + (ts (ts-format form)) + (cons (cons (rec (car form)) + (rec (cdr form)))) + (otherwise form)))) + (format "%S" (rec query)))) + (defun org-ql-view--font-lock-string (mode s) "Return string S font-locked according to MODE." ;; FIXME: Is this the proper way to do this? It works, but I feel like there must be a built-in way... From 501ab1543b596187565c12b401fa3528c46c73c2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 30 Dec 2019 22:45:31 -0600 Subject: [PATCH 037/560] Notes: Add overlay-based cache idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index ba8a203..8470360 100644 --- a/notes.org +++ b/notes.org @@ -586,6 +586,10 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** MAYBE Overlay-based caching inspired by org-num-mode + +[2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. + ** MAYBE [#C] Fancier searching for inherited tags When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. From a513f25b4ae5c1fe8f08e7f9a128b899da637dca Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 31 Dec 2019 21:13:50 -0600 Subject: [PATCH 038/560] Tests: Declare buttercup dependency Used in makem.sh to parse test dependencies. --- tests/test-org-ql.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 60a2cb1..55ff334 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2019 Adam Porter ;; Author: Adam Porter +;; Package-Requires: ((buttercup)) ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -66,6 +67,8 @@ (defun org-ql-test--format-result--query-preamble (sexp) (-let* (((query preamble) (eval sexp)) (preamble (when preamble + ;; NOTE: `xr' is used here, but this function is only called by + ;; interactive helper commands in this file, not when running tests. (xr preamble 'brief)))) (format "`(%S ,(rx %S))" query preamble))) From 6a97f1d95a6963df5d064739955aa5909b7b7255 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 31 Dec 2019 21:14:51 -0600 Subject: [PATCH 039/560] Meta: Update makem,sh, Makefile --- Makefile | 16 +++++++- makem.sh | 116 +++++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 118 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 9be2568..2c1de7a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,16 @@ -# * Verbosity +# * Arguments + +# For consistency, we use only var=val options, not hyphen-prefixed options. + +ifdef autoinstall + AUTOINSTALL = "--auto-install" +endif + +ifdef sandbox + SANDBOX = "--sandbox" +endif + +# ** Verbosity # Since the "-v" in "make -v" gets intercepted by Make itself, we have # to use a variable. @@ -14,4 +26,4 @@ endif # * Rules %: - @./makem.sh $(VERBOSE) $(@) + @./makem.sh $(VERBOSE) $(SANDBOX) $(AUTOINSTALL) $(@) diff --git a/makem.sh b/makem.sh index 67a92db..d4ea826 100755 --- a/makem.sh +++ b/makem.sh @@ -2,8 +2,32 @@ # * makem.sh --- Script to aid building and testing Emacs Lisp packages +# https://github.com/alphapapa/makem.sh + # * Commentary: +# makem.sh is a script helps to build, lint, and test Emacs Lisp +# packages. It aims to make linting and testing as simple as possible +# without requiring per-package configuration. + +# It works similarly to a Makefile in that "rules" are called to +# perform actions such as byte-compiling, linting, testing, etc. + +# Source and test files are discovered automatically from the +# project's Git repo, and package dependencies within them are parsed +# automatically. + +# Output is simple: by default, there is no output unless errors +# occur. With increasing verbosity levels, more detail gives positive +# feedback. Output is colored by default to make reading easy. + +# When desired, emacs-sandbox.sh can be used as a backend, which +# allows package dependencies to be installed automatically into a +# clean Emacs "sandbox" configuration without affecting the +# developer's personal configuration. This is especially helpful when +# upstream dependencies may have released new versions that differ +# from those installed in the developer's personal configuration. See +# . # * License: @@ -145,21 +169,21 @@ EOF # ** Emacs function run_emacs { - debug "run_emacs: emacs -Q --batch --load=$package_initialize_file -L \"$load_path\" $@" + debug "run_emacs: $emacs_command -Q --batch --load=$package_initialize_file -L \"$load_path\" $@" if [[ $debug_load_path ]] then - debug $(emacs -Q --batch \ - --load=$package_initialize_file \ - -L "$load_path" \ - --eval "(message \"LOAD-PATH: %s\" load-path)" \ - 2>&1) + debug $($emacs_command -Q --batch \ + --load=$package_initialize_file \ + -L "$load_path" \ + --eval "(message \"LOAD-PATH: %s\" load-path)" \ + 2>&1) fi output_file=$(mktemp) - emacs -Q --batch \ - --load=$package_initialize_file \ - -L "$load_path" \ - "$@" \ + $emacs_command -Q --batch \ + --load=$package_initialize_file \ + -L "$load_path" \ + "$@" \ &>$output_file exit=$? @@ -224,6 +248,15 @@ function files_args { done } +function dependencies { + # Echo list of package dependencies. + egrep '^;; Package-Requires: ' $(project-source-files) $(project-test-files) \ + | egrep -o '\([^([:space:]][^)]*\)' \ + | egrep -o '^[^[:space:])]+' \ + | sed -r 's/\(//g' \ + | egrep -v '^emacs$' # Ignore Emacs version requirement. +} + # ** Utility function cleanup { @@ -329,7 +362,6 @@ Options: -d, --debug Print debug info. -h, --help I need somebody! -v, --verbose Increase verbosity, up to -vv. - --debug-load-path Print load-path. -f FILE, --file FILE Check FILE in addition to discovered files. @@ -337,8 +369,19 @@ Options: --no-color Disable color output. -C, --no-compile Don't compile files automatically. +Sandbox options: + These require emacs-sandbox.sh to be on your PATH. Find it at + . + + --sandbox Run Emacs with emacs-sandbox.sh. + --auto-install Automatically install package dependencies. + -i, --install PACKAGE Install PACKAGE before running rules. + Source files are automatically discovered from git, or may be specified with options. + +Package dependencies are discovered from "Package-Requires" headers in +source files. EOF } @@ -444,6 +487,8 @@ function test-ert { # * Defaults +emacs_command="emacs" + # TODO: Disable color if not outputting to a terminal. color=true errors=0 @@ -474,12 +519,15 @@ COLOR_white='\e[0;37m' # * Args -args=$(getopt -n "$0" -o dhvf:C -l debug,debug-load-path,help,verbose,file:,no-color,no-compile -- "$@") || { usage; exit 1; } +args=$(getopt -n "$0" -o dhi:svf:C -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox -- "$@") || { usage; exit 1; } eval set -- "$args" while true do case "$1" in + --auto-install) + auto_install=true + ;; -d|--debug) debug=true verbose=2 @@ -491,6 +539,13 @@ do usage exit ;; + -i|--install) + shift + sandbox_install_packages_args+=(--install "$1") + ;; + -s|--sandbox) + sandbox=true + ;; -v|--verbose) ((verbose++)) ;; @@ -523,6 +578,43 @@ debug "Remaining args: ${rest[@]}" trap cleanup EXIT INT TERM +if [[ $sandbox ]] +then + # Setup sandbox. + config_dir=$(mktemp -d) || die "Unable to make temp dir." + temp_paths+=("$config_dir") + + sandbox_basic_args=( + -d "$config_dir" + ) + [[ $debug ]] && sandbox_basic_args+=(--debug) + + if [[ $auto_install ]] + then + deps=($(dependencies)) + debug "Installing dependencies: ${deps[@]}" + + for package in "${deps[@]}" + do + sandbox_install_packages_args+=(--install $package) + done + fi + + # Initialize the sandbox (installs packages once rather than for + # every rule. + emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- " + debug "Initializing sandbox..." + + run_emacs || die "Unable to initialize sandbox." + + # After the sandbox is initialized and packages are installed, set + # the command to prevent the package lists from being refreshed on + # each invocation. + emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} --no-refresh-packages -- " + + debug "Sandbox initialized." +fi + if ! [[ ${project_source_files[@]} ]] then error "No files specified and not in a git repo." From b7e146862d34bdfc0cbfee8d4b140244f02e679d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 31 Dec 2019 21:16:45 -0600 Subject: [PATCH 040/560] Meta: Add pre-push hook to repo This doesn't cause it to be run, of course, but it can be symlinked into place by the user. Better to commit it than to lose it by accident sometime. --- hooks/pre-push | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 hooks/pre-push diff --git a/hooks/pre-push b/hooks/pre-push new file mode 100755 index 0000000..34976fa --- /dev/null +++ b/hooks/pre-push @@ -0,0 +1,17 @@ +#!/bin/sh + +# * Commit parameters +# Unused now, but good for future reference. See man 5 githooks. + +remote="$1" +url="$2" + +read local_ref local_sha remote_ref remote_sha + +# * Run tests + +# Not using sandbox and auto-install, because "git push" shouldn't +# cause remote code to be downloaded and executed (i.e. what would +# happen by installing packages). It can be done manually when needed. + +make test From e1c55b5568f62eae7a6ad499c82ba07595023754 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 1 Jan 2020 02:37:25 -0600 Subject: [PATCH 041/560] Meta: Update makem.sh --- Makefile | 3 +++ makem.sh | 45 +++++++++++++++++++++++++++++++++------------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 2c1de7a..51969fe 100644 --- a/Makefile +++ b/Makefile @@ -25,5 +25,8 @@ endif # * Rules +# TODO: Handle cases in which "test" or "tests" are called and a +# directory by that name exists, which can confuse Make. + %: @./makem.sh $(VERBOSE) $(SANDBOX) $(AUTOINSTALL) $(@) diff --git a/makem.sh b/makem.sh index d4ea826..ab8baa9 100755 --- a/makem.sh +++ b/makem.sh @@ -248,6 +248,23 @@ function files_args { done } +function buttercup-tests-p { + # Return 0 if Buttercup tests are found. + debug "Checking for Buttercup tests..." + + grep "(require 'buttercup)" $(project-test-files) &>/dev/null +} + +function ert-tests-p { + # Return 0 if ERT tests are found. + debug "Checking for ERT tests..." + + # We check for this rather than "(require 'ert)", because ERT may + # already be loaded in Emacs and might not be loaded with + # "require" in a test file. + grep "(ert-deftest" $(project-test-files) &>/dev/null +} + function dependencies { # Echo list of package dependencies. egrep '^;; Package-Requires: ' $(project-source-files) $(project-test-files) \ @@ -451,12 +468,14 @@ function lint-package { } function tests { - # Run tests. + verbose 1 "Running all tests..." + test-ert test-buttercup } function test-buttercup { + buttercup-tests-p || return 0 compile || die verbose 1 "Running Buttercup tests..." @@ -473,6 +492,7 @@ function test-buttercup { } function test-ert { + ert-tests-p || return 0 compile || die verbose 1 "Running ERT tests..." @@ -578,9 +598,17 @@ debug "Remaining args: ${rest[@]}" trap cleanup EXIT INT TERM +if ! [[ ${project_source_files[@]} ]] +then + error "No files specified and not in a git repo." + exit 1 +fi + if [[ $sandbox ]] then # Setup sandbox. + type emacs-sandbox.sh &>/dev/null || die "emacs-sandbox.sh not found." + config_dir=$(mktemp -d) || die "Unable to make temp dir." temp_paths+=("$config_dir") @@ -600,27 +628,20 @@ then done fi - # Initialize the sandbox (installs packages once rather than for - # every rule. + # Initialize the sandbox (installs packages once rather than for every rule). emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- " debug "Initializing sandbox..." run_emacs || die "Unable to initialize sandbox." - # After the sandbox is initialized and packages are installed, set - # the command to prevent the package lists from being refreshed on - # each invocation. + # After the sandbox is initialized and packages are installed, set the command + # to prevent the package lists from being refreshed on each invocation. emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} --no-refresh-packages -- " debug "Sandbox initialized." fi -if ! [[ ${project_source_files[@]} ]] -then - error "No files specified and not in a git repo." - exit 1 -fi - +# Run rules. for rule in "${rest[@]}" do if type "$rule" 2>/dev/null | grep "$rule is a function" &>/dev/null From 317b2ec1b7c0ac56e49599e6ab531dd79584f0eb Mon Sep 17 00:00:00 2001 From: Enis OEZGEN Date: Thu, 2 Jan 2020 14:34:12 +0100 Subject: [PATCH 042/560] Docs: Fix outdated example --- examples.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples.org b/examples.org index 830e77e..af84e17 100644 --- a/examples.org +++ b/examples.org @@ -68,7 +68,7 @@ Show entries that have any timestamp within the past week. Group by date using '(ts :from -7 :to today) :title "Recent Items" :sort '(date priority todo) - :groups '((:auto-ts t))) + :super-groups '((:auto-ts t))) #+END_SRC * Find entries matching a certain =CUSTOM_ID= From 6004ab98da7be4a7b6b8bdd26a6929da30992448 Mon Sep 17 00:00:00 2001 From: Yiming Chen Date: Wed, 1 Jan 2020 15:26:51 +0800 Subject: [PATCH 043/560] Fix: (view--add-todo-face) Bind org-done-keywords org-get-todo-face uses org-done-keywords, which is a buffer-local variable, so it may be nil in the context that org-ql-view--add-todo-face is called. See, e.g. org-agenda-highlight-todo, which does the same thing. Thanks to Yiming Chen (@dsdshcym). --- README.org | 1 + org-ql-view.el | 3 ++- org-ql.info | 26 ++++++++++++++------------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 0235712..b4db8a6 100644 --- a/README.org +++ b/README.org @@ -394,6 +394,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Fixed* + Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to [[https://github.com/matthuszagh][Matt Huszagh]] for reporting.) + Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. ++ Face for done to-do keywords in =org-ql-view= buffers. (Thanks to [[https://github.com/dsdshcym][Yiming Chen]].) *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql-view.el b/org-ql-view.el index 0309a91..ae7478a 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -634,7 +634,8 @@ property." (defun org-ql-view--add-todo-face (keyword) "Return KEYWORD with TODO face added." - (when-let ((face (org-get-todo-face keyword))) + (when-let* ((org-done-keywords org-done-keywords-for-agenda) + (face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) ;;;; Footer diff --git a/org-ql.info b/org-ql.info index 329057f..c11519c 100644 --- a/org-ql.info +++ b/org-ql.info @@ -729,6 +729,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog Huszagh (https://github.com/matthuszagh) for reporting.) • Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling end-of-buffer. + • Face for done to-do keywords in org-ql-view buffers. (Thanks to + Yiming Chen (https://github.com/dsdshcym).) *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -1021,18 +1023,18 @@ Node: Agenda-like views18276 Node: Listing / acting-on results19681 Node: Changelog24283 Node: 04-pre24820 -Node: 03226512 -Node: 03126893 -Node: 0327088 -Node: 02330061 -Node: 02230287 -Node: 02130553 -Node: 0230750 -Node: 0134783 -Node: Notes34882 -Node: Comparison with Org Agenda searches35044 -Node: org-sidebar35915 -Node: License36194 +Node: 03226633 +Node: 03127014 +Node: 0327209 +Node: 02330182 +Node: 02230408 +Node: 02130674 +Node: 0230871 +Node: 0134904 +Node: Notes35003 +Node: Comparison with Org Agenda searches35165 +Node: org-sidebar36036 +Node: License36315  End Tag Table From b1d9fcf27454d6ddeabab3f660008f4e069404cc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 03:51:50 -0600 Subject: [PATCH 044/560] Meta: Update Makefile, makem.sh --- Makefile | 19 +++++- makem.sh | 185 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 116 insertions(+), 88 deletions(-) diff --git a/Makefile b/Makefile index 51969fe..5000738 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,27 @@ # For consistency, we use only var=val options, not hyphen-prefixed options. -ifdef autoinstall - AUTOINSTALL = "--auto-install" +# NOTE: I don't like duplicating the arguments here and in makem.sh, +# but I haven't been able to find a way to pass arguments which +# conflict with Make's own arguments through Make to the script. +# Using -- doesn't seem to do it. + +ifdef auto-install + AUTO_INSTALL = "--auto-install" endif ifdef sandbox SANDBOX = "--sandbox" endif +ifdef sandbox-dir + SANDBOX_DIR = "--sandbox-dir" "$(sandbox-dir)" +endif + +ifdef debug + DEBUG = "--debug" +endif + # ** Verbosity # Since the "-v" in "make -v" gets intercepted by Make itself, we have @@ -29,4 +42,4 @@ endif # directory by that name exists, which can confuse Make. %: - @./makem.sh $(VERBOSE) $(SANDBOX) $(AUTOINSTALL) $(@) + @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR) $(AUTO_INSTALL) $(@) diff --git a/makem.sh b/makem.sh index ab8baa9..d63285c 100755 --- a/makem.sh +++ b/makem.sh @@ -44,63 +44,9 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# * Safety +# * Functions -# NOTE: These are disabled by default in this template but should be -# enabled when feasible. Documentation is from the Bash man page. - -# ** errexit - -# Exit immediately if a pipeline (which may consist of a single simple -# command), a list, or a compound command (see SHELL GRAMMAR above), -# exits with a non-zero status. The shell does not exit if the -# command that fails is part of the command list immediately following -# a while or until keyword, part of the test following the if or elif -# reserved words, part of any command executed in a && or || list -# except the command follow‐ ing the final && or ||, any command in a -# pipeline but the last, or if the command's return value is being -# inverted with !. If a compound command other than a subshell -# returns a non-zero status because a command failed while -e was -# being ignored, the shell does not exit. A trap on ERR, if set, is -# executed before the shell exits. This option applies to the shell -# environment and each subshell environment separately (see COMMAND -# EXECUTION ENVIRONMENT above), and may cause subshells to exit before -# executing all the commands in the subshell. - -# If a compound command or shell function executes in a context where -# -e is being ignored, none of the commands executed within the -# compound command or function body will be affected by the -e -# setting, even if -e is set and a command returns a failure status. -# If a compound command or shell function sets -e while executing in a -# context where -e is ignored, that setting will not have any effect -# until the compound command or the command containing the function -# call completes. - -# set -o errexit - -# ** nounset - -# Treat unset variables and parameters other than the special -# parameters "@" and "*" as an error when performing parameter -# expansion. If expansion is attempted on an unset variable or -# parameter, the shell prints an error message, and, if not -# interactive, exits with a non-zero status. - -# NOTE: When this is not enabled, individual variables can be required -# to be set by using "${var:?}" parameter expansion syntax. - -# set -o nounset - -# ** pipefail - -# If set, the return value of a pipeline is the value of the last -# (rightmost) command to exit with a non-zero status, or zero if all -# commands in the pipeline exit successfully. This option is disabled -# by default. - -# set -o pipefail - -# * Elisp +# ** Elisp # These functions return a path to an elisp file which can be loaded # by Emacs on the command line with -l or --load. @@ -164,8 +110,6 @@ EOF echo $file } -# * Functions - # ** Emacs function run_emacs { @@ -219,17 +163,27 @@ function project-elisp-files { function project-source-files { # Echo list of Elisp files that are not tests. - project-elisp-files | egrep -v '^tests?/test-?' + project-elisp-files | egrep -v "$test_files_regexp" | feature-files } function project-test-files { # Echo list of Elisp test files. - project-elisp-files | egrep '^tests?/test-?' + project-elisp-files | egrep "$test_files_regexp" } function exclude-files { # Filter out paths (STDIN) which should be excluded by default. - egrep -v "(/\.cask/|-autoloads.el)" + egrep -v "(/\.cask/|-autoloads.el|.dir-locals)" +} + +function feature-files { + # Read paths on STDIN and echo ones that (provide 'a-feature). + while read path + do + debug "PATH: $path" + egrep "^\\(provide '" "$path" &>/dev/null \ + && echo "$path" + done } function load-files-args { @@ -248,30 +202,46 @@ function files_args { done } +function test-files-p { + # Return 0 if $project_test_files is non-empty. + [[ "${project_test_files[@]}" ]] +} + function buttercup-tests-p { # Return 0 if Buttercup tests are found. + test-files-p || die "No tests found." debug "Checking for Buttercup tests..." - grep "(require 'buttercup)" $(project-test-files) &>/dev/null + grep "(require 'buttercup)" "${project_test_files[@]}" &>/dev/null } function ert-tests-p { # Return 0 if ERT tests are found. + test-files-p || die "No tests found." debug "Checking for ERT tests..." # We check for this rather than "(require 'ert)", because ERT may # already be loaded in Emacs and might not be loaded with # "require" in a test file. - grep "(ert-deftest" $(project-test-files) &>/dev/null + grep "(ert-deftest" "${project_test_files[@]}" &>/dev/null } function dependencies { # Echo list of package dependencies. + + # Search package headers. egrep '^;; Package-Requires: ' $(project-source-files) $(project-test-files) \ | egrep -o '\([^([:space:]][^)]*\)' \ | egrep -o '^[^[:space:])]+' \ | sed -r 's/\(//g' \ | egrep -v '^emacs$' # Ignore Emacs version requirement. + + # Search Cask file. + if [[ -r Cask ]] + then + egrep '\(depends-on "[^"]+"' Cask \ + | sed -r -e 's/\(depends-on "([^"]+)".*/\1/g' + fi } # ** Utility @@ -390,7 +360,10 @@ Sandbox options: These require emacs-sandbox.sh to be on your PATH. Find it at . - --sandbox Run Emacs with emacs-sandbox.sh. + -s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary + directory (removing directory on exit). + -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it + on exit). Implies -s. --auto-install Automatically install package dependencies. -i, --install PACKAGE Install PACKAGE before running rules. @@ -398,7 +371,7 @@ Source files are automatically discovered from git, or may be specified with options. Package dependencies are discovered from "Package-Requires" headers in -source files. +source files and from a Cask file. EOF } @@ -507,24 +480,38 @@ function test-ert { # * Defaults +test_files_regexp='^(tests?|t)/' emacs_command="emacs" - -# TODO: Disable color if not outputting to a terminal. -color=true errors=0 verbose=0 - compile=true + +# MAYBE: Disable color if not outputting to a terminal. (OTOH, the +# colorized output is helpful in CI logs, and I don't know if, +# e.g. GitHub Actions logging pretends to be a terminal.) +color=true + +# TODO: Using the current directory (i.e. a package's repo root directory) in +# load-path can cause weird errors in case of--you guessed it--stale .ELC files, +# the zombie problem that just won't die. It's incredible how many different ways +# this problem presents itself. In this latest example, an old .ELC file, for a +# .EL file that had since been renamed, was present on my local system, which meant +# that an example .EL file that hadn't been updated was able to "require" that .ELC +# file's feature without error. But on another system (in this case, trying to +# setup CI using GitHub Actions), the old .ELC was not present, so the example .EL +# file was not able to load the feature, which caused a byte-compilation error. + +# In this case, I will prevent such example files from being compiled. But in +# general, this can cause weird problems that are tedious to debug. I guess +# the best way to fix it would be to actually install the repo's code as a +# package into the sandbox, but doing that would require additional tooling, +# pulling in something like Quelpa or package-build--and if the default recipe +# weren't being used, the actual recipe would have to be fetched off MELPA or +# something, which seems like getting too smart for our own good. + +# TODO: Emit a warning if .ELC files that don't match any .EL files are detected. load_path="." -# TODO: Option to not byte-compile test files. -project_byte_compile_files=($(project-elisp-files)) -project_source_files=($(project-source-files)) -project_test_files=($(project-test-files)) - -package_initialize_file="$(elisp-package-initialize-file)" -temp_paths+=("$package_initialize_file") - # ** Colors COLOR_off='\e[0m' @@ -537,9 +524,24 @@ COLOR_purple='\e[0;35m' COLOR_cyan='\e[0;36m' COLOR_white='\e[0;37m' +# * Project files + +# MAYBE: Option to not byte-compile test files. (OTOH, byte-compiling reveals many +# errors that would otherwise go unnoticed, so it's worth it to fix the warnings.) +project_source_files=($(project-source-files)) +project_test_files=($(project-test-files)) +project_byte_compile_files=("${project_source_files[@]}" "${project_test_files[@]}") + +package_initialize_file="$(elisp-package-initialize-file)" +temp_paths+=("$package_initialize_file") + # * Args -args=$(getopt -n "$0" -o dhi:svf:C -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox -- "$@") || { usage; exit 1; } +args=$(getopt -n "$0" \ + -o dhi:sS:vf:C \ + -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox,sandbox-dir: \ + -- "$@") \ + || { usage; exit 1; } eval set -- "$args" while true @@ -566,6 +568,11 @@ do -s|--sandbox) sandbox=true ;; + -S|--sandbox-dir) + shift + sandbox=true + sandbox_dir="$1" + ;; -v|--verbose) ((verbose++)) ;; @@ -609,16 +616,21 @@ then # Setup sandbox. type emacs-sandbox.sh &>/dev/null || die "emacs-sandbox.sh not found." - config_dir=$(mktemp -d) || die "Unable to make temp dir." - temp_paths+=("$config_dir") + if ! [[ $sandbox_dir ]] + then + # No sandbox dir specified: make temp dir and remove it on exit. + sandbox_dir=$(mktemp -d) || die "Unable to make temp dir." + temp_paths+=("$sandbox_dir") + fi sandbox_basic_args=( - -d "$config_dir" + -d "$sandbox_dir" ) [[ $debug ]] && sandbox_basic_args+=(--debug) if [[ $auto_install ]] then + # Add dependencies to package install list. deps=($(dependencies)) debug "Installing dependencies: ${deps[@]}" @@ -628,11 +640,14 @@ then done fi - # Initialize the sandbox (installs packages once rather than for every rule). - emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- " - debug "Initializing sandbox..." + if [[ ${sandbox_install_packages_args[@]} ]] + then + # Initialize the sandbox (installs packages once rather than for every rule). + emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- " + debug "Initializing sandbox..." - run_emacs || die "Unable to initialize sandbox." + run_emacs || die "Unable to initialize sandbox." + fi # After the sandbox is initialized and packages are installed, set the command # to prevent the package lists from being refreshed on each invocation. From 3cc7ebe5b494fdff4f01778b94d337ed182bde38 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 03:57:05 -0600 Subject: [PATCH 045/560] Meta: Add CI using GitHub Actions Using test.yml from makem.sh repo. --- .github/workflows/test.yml | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..475ab9c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,72 @@ +# * test.yml --- Test Emacs packages using makem.sh on GitHub Actions + +# https://github.com/alphapapa/makem.sh + +# Based on Steve Purcell's examples at +# , +# . + +# * License: + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# * Code: + +name: "CI" +on: + pull_request: + push: + # branches: + # - master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + emacs_version: + - 26.3 + - snapshot + steps: + - uses: purcell/setup-emacs@master + with: + version: ${{ matrix.emacs_version }} + + - uses: actions/checkout@v1 + + - name: Install sandbox script + run: | + curl -o $GITHUB_WORKSPACE/emacs-sandbox.sh \ + https://raw.githubusercontent.com/alphapapa/emacs-sandbox.sh/master/emacs-sandbox.sh + chmod +x $GITHUB_WORKSPACE/emacs-sandbox.sh + echo ::add-path::$GITHUB_WORKSPACE + echo ::set-env name=SANDBOX_DIR::$(mktemp -d) + + - name: Initialize sandbox + run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --auto-install --install package-lint + + # The "all" rule is not used, because it treats compilation warnings + # as failures, so linting and testing are run as separate steps. + + - name: Lint + run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint + + - name: Test + if: always() # Run test even if linting fails. + run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR test + +# Local Variables: +# eval: (outline-minor-mode) +# End: From 689a1970660c49d890635525f722c0288e5aab0f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 04:11:52 -0600 Subject: [PATCH 046/560] Meta: Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e5e85fc..28f3b16 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .#* /scratch.el .cask +/sandbox/ From e9d5bca84205efa2b00957acd2c34eaa49b44a0c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 04:12:59 -0600 Subject: [PATCH 047/560] Comment: Add headings --- org-ql.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org-ql.el b/org-ql.el index 22e3708..9d47132 100644 --- a/org-ql.el +++ b/org-ql.el @@ -784,10 +784,13 @@ replace the clause with a preamble." ;; Always check contents with predicate. element) + ;; Scheduled. (`(scheduled . ,_) (setq org-ql-preamble org-scheduled-time-regexp) ;; Return element, because the predicate still needs testing. element) + + ;; Tags. (`((or 'tags-local 'local-tags 'tags-l 'ltags) . ,tags) ;; When searching for local, non-inherited tags, we can ;; search directly to headings containing one of the tags. @@ -796,6 +799,8 @@ replace the clause with a preamble." t)) ;; Return nil, because we don't need to test the predicate. nil) + + ;; Timestamps. (`(ts . ,rest) (setq org-ql-preamble (pcase (plist-get rest :type) ((or 'nil 'both) org-tsr-regexp-both) From d28d54c58842f0d31e40e8d21337360c9c238ba0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 05:40:06 -0600 Subject: [PATCH 048/560] Comment: Add/remove TODOs --- helm-org-ql.el | 12 ------------ org-ql.el | 1 + 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index 821ea62..9e231a9 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -195,18 +195,6 @@ Is transformed into this query: (setq helm-org-ql-buffers-files buffers-files)) (ignore-errors ;; Ignore errors that might be caused by partially typed queries. - - ;; FIXME: This doesn't prevent warnings that are errors occurring during - ;; byte-compilation due to partially typed values which can't be correctly - ;; pre-processed, e.g. "ts:to=2019-01-0", which can't be parsed into a - ;; timestamp. A "*Compile-Log*" buffer is displayed with "Error: Wrong type - ;; argument: integerp, nil". With my Helm settings, it's hidden as soon as - ;; the query is typed correctly, so it's tolerable, but I'd prefer to fix it. - ;; I haven't found a way to ignore the error/warning; `with-no-warnings' has - ;; no effect, and we're already using `ignore-errors'. The only solution I - ;; can think of would be to ignore the errors/warnings higher up the chain - ;; where byte-compilation is actually done, but it might not be a good idea - ;; to always ignore such errors/warnings. (org-ql-select buffers-files query :action `(helm-org-ql--heading ,window-width)))))) :match #'identity diff --git a/org-ql.el b/org-ql.el index 9d47132..3f6a3eb 100644 --- a/org-ql.el +++ b/org-ql.el @@ -442,6 +442,7 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." ;; TODO: Use --value-at for tags cache. (defun org-ql--value-at (position fn) + ;; TODO: Either rename to `value-at-point' and remove `position' arg, or move point. "Return FN's value at POSITION in current buffer. Values compared with `equal'." ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables From 84b458d6fef24aff713c8624156a63cf93bd5fd4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 05:43:19 -0600 Subject: [PATCH 049/560] Tidy: Move binding --- helm-org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index 9e231a9..2e4ffb8 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -216,10 +216,10 @@ WINDOW-WIDTH should be the width of the Helm window." ;; call a setup function in a buffer before running queries. (let* ((prefix (concat (buffer-name) ":")) (width (- window-width (length prefix))) + (heading (org-get-heading t)) (path (-> (org-get-outline-path) (org-format-outline-path width nil "") (org-split-string ""))) - (heading (org-get-heading t)) (path (if helm-org-ql-reverse-paths (concat heading "\\" (s-join "\\" (nreverse path))) (concat (s-join "/" path) "/" heading)))) From fbff8720b0f30a1f869af5d26347236f35ee2157 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 05:47:00 -0600 Subject: [PATCH 050/560] Tidy: Habit preamble No need for rx-to-string, because it's static. --- org-ql.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 3f6a3eb..9f7d939 100644 --- a/org-ql.el +++ b/org-ql.el @@ -676,9 +676,7 @@ replace the clause with a preamble." ;; Return nil, don't test the predicate. nil) (`(habit) - ;; TODO: Move regexp to const. - (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":STYLE:" (1+ space) - "habit" (0+ space) eol))) + (setq org-ql-preamble (rx bol (0+ space) ":STYLE:" (1+ space) "habit" (0+ space) eol)) nil) ;; Heading text. From 19833cbbecb5b38a46b202d1b8dc50c756a8337c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 06:57:54 -0600 Subject: [PATCH 051/560] Tidy: Docstrings --- org-ql-view.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index ae7478a..08babe7 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -107,7 +107,7 @@ Based on `org-agenda-mode-map'.") (const :tag "Right" right))) (defcustom org-ql-view-no-other-window nil - "Whether `other-window' commands should cycle through the `org-ql-views' sidebar window. + "Whether `other-window' commands should cycle through `org-ql-views' sidebar. See info node `(elisp)Cyclic Window Ordering'." :type 'boolean) @@ -385,7 +385,8 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', (goto-char (point-min)))))) (defun org-ql-view--header-line-format (buffers-files query &optional title) - "Return header-line-format for BUFFERS-FILES and QUERY." + "Return `header-line-format' for BUFFERS-FILES and QUERY. +If TITLE, prepend it to the header." (let* ((title (if title (concat (propertize "View:" 'face 'org-agenda-structure) title " ") From 997765f9ea6ff1695c56b80fd28f3cec134ae24e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 3 Jan 2020 07:02:06 -0600 Subject: [PATCH 052/560] Tidy: Comment out unused form Removes a linter warning for now. --- tests/test-org-ql.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 55ff334..0b0a855 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -59,9 +59,11 @@ (defun org-ql-test--format-result--ql (sexp) (let* ((value (eval sexp)) - (prefix (if (and value (listp value)) - "'" - ""))) + ;; FIXME: Not sure why this is currently unused. Commenting out for now. + ;; (prefix (if (and value (listp value)) + ;; "'" + ;; "")) + ) (format "%S" value))) (defun org-ql-test--format-result--query-preamble (sexp) From fb830f8577bb6287d899948f696e33c96e877a40 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Jan 2020 01:45:57 -0600 Subject: [PATCH 053/560] Meta: (test.yml) Use checkout@v2 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 475ab9c..b56b721 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -44,7 +44,7 @@ jobs: with: version: ${{ matrix.emacs_version }} - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Install sandbox script run: | From 2af951593408538e5b8f1c9b753459e57b00192e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Jan 2020 08:32:41 -0600 Subject: [PATCH 054/560] Notes: Add about org-element cache --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 8470360..835389d 100644 --- a/notes.org +++ b/notes.org @@ -991,6 +991,10 @@ John + [[https://github.com/m00natic/cl-fdbq][GitHub - m00natic/cl-fdbq: SQL-like operations over fixed field DBs]] +** Nicolas Goaziou's =org-element= cache implementation + +[2020-01-04 Sat 08:31] https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el#L4817 I guess I haven't been keeping up, because I'm not sure when exactly he made or committed this, or what his plans for it are. It's currently disabled by default. + * Examples / testing #+BEGIN_SRC elisp From fa1e3354b696fdda5ce29850f20e538627783bb7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Jan 2020 09:03:32 -0600 Subject: [PATCH 055/560] Notes: Add org-sql --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 835389d..97887dc 100644 --- a/notes.org +++ b/notes.org @@ -995,6 +995,10 @@ John [2020-01-04 Sat 08:31] https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el#L4817 I guess I haven't been keeping up, because I'm not sure when exactly he made or committed this, or what his plans for it are. It's currently disabled by default. +** [[https://github.com/ndwarshuis/org-sql][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] + +[2020-01-04 Sat 09:03] + * Examples / testing #+BEGIN_SRC elisp From 21c7dc15878f90eddee6375faf6b138d7784579c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 7 Jan 2020 08:51:19 -0600 Subject: [PATCH 056/560] Notes: Add idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 97887dc..c091573 100644 --- a/notes.org +++ b/notes.org @@ -594,6 +594,10 @@ This works okay (except the priority accessor needs to be fixed, because Org pri When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** MAYBE Use Bovine or Wisent to parse non-sexp syntax + +They're both built-in to Emacs, so we could drop the =peg= dependency. + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. From d2f7b06f3d4b86293bc51c31768bf96d77c6e185 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 06:48:11 -0600 Subject: [PATCH 057/560] Tests: Rename symbols, fix loading test data interactively --- tests/test-org-ql.el | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 0b0a855..8fe0e8d 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -45,7 +45,7 @@ ('org-ql--pre-process-query t) (_ nil))) (result (pcase sexp - (`(org-ql-expect ,args) (org-ql-test--format-result--ql `(org-ql test-buffer + (`(org-ql-expect ,args) (org-ql-test--format-result--ql `(org-ql org-ql-test-buffer ,@args :action (org-ql-test-org-get-heading)))) (`(org-ql . _) (org-ql-test--format-result--ql sexp)) @@ -80,7 +80,7 @@ (if-let* ((sexp (elisp--preceding-sexp)) (sexp (pcase sexp (`(org-ql . ,_) (setf (car sexp) 'org-ql-agenda)) - (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-select test-buffer + (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-select org-ql-test-buffer ',@ql-args))) (_ nil)))) @@ -110,7 +110,7 @@ Based on Buttercup macro `it'." RESULTS should be a list of strings as returned by `org-ql-test-org-get-heading'." (declare (indent defun)) - `(expect (org-ql test-buffer + `(expect (org-ql org-ql-test-buffer ,@ql-args :action (org-ql-test-org-get-heading)) :to-equal ,results)) @@ -138,14 +138,16 @@ RESULTS should be a list of strings as returned by ;; For Org 9.1.9. (substring-no-properties (org-get-heading t t t t)))) - (setq test-buffer (find-file-noselect (concat default-directory "tests/data.org")) + (setq org-ql-test-buffer (->> (locate-dominating-file default-directory ".git") + (expand-file-name "tests/data.org") + find-file-noselect) ;; For manual testing: - ;; test-buffer (find-file-noselect "data.org") - num-headings (with-current-buffer test-buffer - (org-with-wide-buffer - (goto-char (point-min)) - (cl-loop while (re-search-forward org-heading-regexp nil t) - sum 1))))) + ;; org-ql-test-buffer (find-file-noselect "data.org") + org-ql-test-num-headings (with-current-buffer org-ql-test-buffer + (org-with-wide-buffer + (goto-char (point-min)) + (cl-loop while (re-search-forward org-heading-regexp nil t) + sum 1))))) (describe "Caching" @@ -180,21 +182,21 @@ RESULTS should be a list of strings as returned by (describe "Query functions/macros" (it "org-ql" - (expect (length (org-ql test-buffer + (expect (length (org-ql org-ql-test-buffer (category) :sort deadline)) - :to-equal num-headings)) + :to-equal org-ql-test-num-headings)) (it "org-ql-select" - (expect (length (org-ql-select test-buffer + (expect (length (org-ql-select org-ql-test-buffer '(category) :sort 'deadline)) - :to-equal num-headings)) + :to-equal org-ql-test-num-headings)) (it "org-ql-query" (expect (length (org-ql-query :select 'element - :from test-buffer + :from org-ql-test-buffer :where '(category) :order-by 'date)) - :to-equal num-headings))) + :to-equal org-ql-test-num-headings))) (it "Query pre-processing" (expect (org-ql--pre-process-query '(and "string1" "string2")) @@ -330,9 +332,9 @@ RESULTS should be a list of strings as returned by (describe "(category)" (org-ql-it "without arguments" - (expect (length (org-ql test-buffer + (expect (length (org-ql org-ql-test-buffer (category))) - :to-equal num-headings)) + :to-equal org-ql-test-num-headings)) (org-ql-it "with a category" (org-ql-expect ((category "ambition")) From 2a7440b6398bc4af0fb65cddf299a6234365a8c3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 08:59:11 -0600 Subject: [PATCH 058/560] Tests: Move non-test-data to notes.org --- notes.org | 440 ++++++++++++++++++++++++++++++++++++++ tests/data.org | 488 ++----------------------------------------- tests/test-org-ql.el | 82 ++++---- 3 files changed, 504 insertions(+), 506 deletions(-) diff --git a/notes.org b/notes.org index c091573..acc514b 100644 --- a/notes.org +++ b/notes.org @@ -2794,4 +2794,444 @@ Benchmark results: | cached | 6.51 | 0.519871 | 0 | 0 | | uncached | slowest | 3.386679 | 0 | 0 | +* Testing + +[2020-01-08 Wed 07:15] Subtree moved from =tests/data.org=. + +#+BEGIN_SRC elisp + (cl-defun ap/org-tweak-timestamps (&key (offset 0) epoch-ts) + "Advance all timestamps in the current buffer as if the earliest one was on today. + OFFSET changes which timestamp (in chronological order) is set to + today. Or, if EPOCH-TS is non-nil, use it as the new zero-point + for today." + (let* ((tss (->> (org-with-wide-buffer + (goto-char (point-min)) + (cl-loop while (re-search-forward org-ts-regexp-both nil t) + collect (ts-parse-org (match-string 0)))) + (-sort #'ts<))) + (epoch-ts (if epoch-ts + (ts-parse-org epoch-ts) + (nth offset tss))) + (difference-secs (ts-diff (ts-now) epoch-ts)) + (days (floor (/ difference-secs 86400)))) + (org-with-wide-buffer + (goto-char (point-min)) + (while (re-search-forward org-ts-regexp-both nil t) + (let* ((ts (ts-parse-org (match-string 0))) + (timed-p (string-match-p (rx (repeat 2 digit) ":" (repeat 2 digit) (or ">" "]")) (match-string 0))) + (type (cond ((string-prefix-p "<" (match-string 0)) 'active) + ((string-prefix-p "[" (match-string 0)) 'inactive) + (t (error "Unknown ts type")))) + (brackets (cl-ecase type + ('active (cons "<" ">")) + ('inactive (cons "[" "]")))) + (format-string (concat (car brackets) + (if timed-p + "%Y-%m-%d %a %H:%M" + "%Y-%m-%d %a") + (cdr brackets))) + (new-ts (ts-adjust 'day days ts)) + (new-ts-string (ts-format format-string new-ts))) + (replace-match new-ts-string t t nil 0)))) + (message "Tweaked from epoch: %s" (ts-format epoch-ts)))) +#+END_SRC + +#+BEGIN_SRC elisp +(org-time-string-to-absolute (org-entry-get (point) "SCHEDULED")) +#+END_SRC + + #+BEGIN_SRC elisp :results none + ;; Setup code + (require 'org-super-agenda) + (org-super-agenda-mode 1) + (require 'org-habit) + (setq org-todo-keywords + '((sequence "TODO(t!)" "TODAY(a!)" "NEXT(n!)" "STARTED(s!)" "IN-PROGRESS(p!)" "UNDERWAY(u!)" "WAITING(w@)" "SOMEDAY(o!)" "MAYBE(m!)" "|" "DONE(d@)" "CANCELED(c@)") + (sequence "CHECK(k!)" "|" "DONE(d@)") + (sequence "TO-READ(r!)" "READING(R!)" "|" "HAVE-READ(d@)") + (sequence "TO-WATCH(!)" "WATCHING(!)" "SEEN(!)"))) + (with-current-buffer "test.org" (revert-buffer)) + + (defmacro with-org-today-date (date &rest body) + "Run BODY with the `org-today' function set to return simply DATE. + DATE should be a date-time string (both date and time must be included)." + (declare (indent defun)) + `(let ((day (date-to-day ,date)) + (orig (symbol-function 'org-today))) + (unwind-protect + (progn + (fset 'org-today (lambda () day)) + ,@body) + (fset 'org-today orig)))) + #+END_SRC + +#+BEGIN_SRC elisp :results none + (defun diary-sunrise () + (let ((dss (diary-sunrise-sunset))) + (with-temp-buffer + (insert dss) + (goto-char (point-min)) + (search-forward ",") + (buffer-substring (point-min) (match-beginning 0))))) + + (defun diary-sunset () + (let ((dss (diary-sunrise-sunset)) + start end) + (with-temp-buffer + (insert dss) + (goto-char (point-min)) + (search-forward ", ") + (setq start (match-end 0)) + (search-forward " at") + (setq end (match-beginning 0)) + (goto-char start) + (capitalize-word 1) + (buffer-substring start end)))) +#+END_SRC + +*Note:* Removing tests from here as they're added to =test.el=. + + #+BEGIN_SRC elisp + + (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:name "Time grid items in all-uppercase with RosyBrown1 foreground" + :time-grid t + :transformer (--> it + (upcase it) + (propertize it 'face '(:foreground "RosyBrown1")))) + (:name "Priority >= C items underlined, on black background" + :face (:background "black" :underline t) + :not (:priority>= "C") + :order 100)))) + (org-agenda nil "a"))) + (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:name none + :time-grid t) + (:name "Should be all-uppercase RosyBrown1 on black" + :face (:background "black" :foreground "RosyBrown1") + :transformer #'upcase + :not (:priority>= "C") + :order 100)))) + (org-agenda nil "a"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:name none + :time-grid t) + (:name none + :not (:priority>= "C") + :order 100)))) + (org-agenda nil "a"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:name "Items with child TODOs" + :children todo)))) + (org-agenda nil "a"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:name "Items with child TODOs" + :children "CHECK")))) + (org-agenda nil "a"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-agenda-custom-commands + '(("u" "Super view" + ((agenda "" ((org-super-agenda-groups + '((:name "Today" + :time-grid t + :scheduled today + :deadline today))))) + (todo "" ((org-super-agenda-groups + '((:name "Projects" + :children t) + (:discard (:anything t))))))))))) + (org-agenda nil "u"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-agenda-custom-commands + '(("u" "Super view" + ((agenda "" ((org-super-agenda-groups + '((:name "Today" + :time-grid today))))) + (todo "" ((org-super-agenda-groups + '((:name "Projects" + :children t) + (:discard (:anything t))))))))))) + (org-agenda nil "u"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-agenda-custom-commands + '(("u" "Super view" + ((agenda "" ((org-super-agenda-groups + '((:name "Schedule" + :time-grid t + :date today) + (:name "Due today" + :deadline today) + (:name "Due soon" + :deadline t))))) + (todo "" ((org-agenda-overriding-header "") + (org-super-agenda-groups + '((:name "Projects" + :children t) + (:discard (:anything t))))))))))) + (org-agenda nil "u"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + (org-super-agenda-groups + '((:scheduled (before "2017-07-06"))))) + (org-agenda nil "a"))) +#+END_SRC + +#+BEGIN_SRC elisp + + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:todo "WAITING"))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) + (org-todo-list))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:todo "SOMEDAY"))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) + (org-tags-view nil "Emacs"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:todo "CHECK"))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) +;; org-search-view doesn't seem to set the todo-state property, so the matcher doesn't work + (org-search-view nil "Emacs"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:regexp ("moon" "mars")))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) + (org-search-view nil "space"))) + + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:todo "SOMEDAY"))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) + (org-agenda-list nil nil 'day))) + +#+END_SRC + +** Agenda examining + +This helps a lot. + +#+BEGIN_SRC elisp + (defun data-debug-show-string-with-properties (s) + (with-current-buffer (get-buffer-create "argh") + (erase-buffer) + (print s (current-buffer)) + + ;; Convert string reader representations to plain lists that can be set + (cl-loop for (match replace) in '(("#(" "'(") + ("#<" "'(") + (">" ")")) + do (progn + (goto-char (point-min)) + (while (search-forward match nil 'noerror) + (replace-match replace 'fixedcase 'literal)))) + + ;; Surround content in a list which `argh' is set to, then eval + ;; the buffer to do it + (goto-char (point-min)) + (insert "(setq argh (list '") + (delete-forward-char 2) + (goto-char (point-max)) + (insert "))") + + ;; Okay, sure, eval'ing the buffer is dangerous and bad and wrong. + ;; But this is the only way I can find to make this work. (Maybe + ;; `text-properties-at' could be used to get actual lists...) + (eval-buffer) + + (data-debug-show-stuff argh "argh") + ;; (switch-to-buffer (current-buffer)) + )) + + (defun data-debug-show-current-line-with-properties () + (interactive) + (data-debug-show-string-with-properties (buffer-substring (line-beginning-position) (line-end-position)))) + + (with-current-buffer "*Org Agenda*" + (data-debug-show-string-with-properties (seq-subseq (split-string (buffer-string) "\n") + 0 5))) +#+END_SRC + +** Agenda censoring + +For sharing screenshots of the agenda without revealing private data. + +#+BEGIN_SRC elisp + (defun org-agenda-sharpie () + "Censor the text of items in the agenda." + (interactive) + (let (regexp old-heading new-heading properties) + ;; Save face properties of line in agenda to reapply to changed text + (setq properties (text-properties-at (point))) + + ;; Go to source buffer + (org-with-point-at (org-find-text-property-in-string 'org-marker + (buffer-substring (line-beginning-position) + (line-end-position))) + ;; Save old heading text and ask for new text + (line-beginning-position) + (unless (org-at-heading-p) + ;; Not sure if necessary + (org-back-to-heading)) + (setq old-heading (when (looking-at org-complex-heading-regexp) + (match-string 4)))) + (setq new-heading (read-from-minibuffer "Overwrite visible heading with: ")) + (add-text-properties 0 (length new-heading) properties new-heading) + ;; Back to agenda buffer + (save-excursion + (when (and old-heading new-heading) + ;; Replace agenda text + (let ((inhibit-read-only t)) + (goto-char (line-beginning-position)) + (when (search-forward old-heading (line-end-position)) + (replace-match new-heading 'fixedcase 'literal))))))) +#+END_SRC + +** Auto grouping + + +#+BEGIN_SRC elisp + (with-org-today-date "2017-07-05 00:00" + (let ((org-super-agenda-groups + '((:auto-group t))) + (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) + (org-agenda-list nil nil 'day))) +#+END_SRC + +** Auto categories + +#+BEGIN_SRC elisp + (let ((org-super-agenda-groups + '((:auto-category t)))) + (org-agenda-list nil nil 'day)) +#+END_SRC + +** Date + +#+BEGIN_SRC elisp + (with-org-today-date "2017-07-05 00:00" + (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) + (last-day-of-month + ;; A hack that seems to work fine + (1+ (calendar-last-day-of-month month year))) + (target-date (format "%d-%02d-%02d" year month last-day-of-month)) + (org-super-agenda-groups + `((:deadline (before ,target-date)) + (:discard (:anything t))))) + (org-todo-list))) + + (with-org-today-date "2017-07-05 00:00" + (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-agenda-span 'day) + ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) + (last-day-of-month (calendar-last-day-of-month month year)) + (target-date (format "%d-%02d-%02d" year month last-day-of-month)) + (org-super-agenda-groups + `((:deadline (before ,target-date)) + (:discard (:anything t))))) + (org-todo-list))) +#+END_SRC + +** Effort + +#+BEGIN_SRC elisp + (with-org-today-date "2017-07-05 00:00" + (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) + (org-super-agenda-groups + '((:effort< "0:06")))) + (org-agenda-list nil nil 'day))) +#+END_SRC + +** Misc + +*** let-plist + +I don't need this right now, but it might come in handy here or elsewhere. + +#+BEGIN_SRC elisp + (defmacro osa/let-plist (keys plist &rest body) + "`cl-destructuring-bind' without the boilerplate for plists." + ;; See https://emacs.stackexchange.com/q/22542/3871 + + ;; I really don't understand why Emacs doesn't have this already. + ;; So many things come close to it: pcase, pcase-let, map-let, + ;; cl-destructuring-bind, -let...but none of them let you simply + ;; bind all the values of a plist to variables with the same name as + ;; their keys. You always have to type the name of the key twice. + + ;; For example, compare these two forms: + + ;; (-let (((&keys :from from :to to :date date :subject subject) email)) + ;; (list from to date subject)) + + ;; (osa/let-plist (:from :to :date :subject) email + ;; (list from to date subject)) + + ;; Now, sure, sometimes you need to bind values to differently named + ;; variables. But when you don't, I know which one I prefer. + (declare (indent defun)) + (setq keys (cl-loop for key in keys + collect (intern (replace-regexp-in-string (rx bol ":") "" + (symbol-name key))))) + `(cl-destructuring-bind + (&key ,@keys &allow-other-keys) + ,plist + ,@body)) +#+END_SRC + +** Profiling + +#+BEGIN_SRC elisp :results none + (defmacro profile-it (times &rest body) + `(let (output) + (dolist (p '("org-super-agenda-" "map" "org-" "string-" "s-" "buffer-" "append" "delq" "map" "list" "car" "save-" "outline-" "delete-dups" "sort" "line-" "nth" "concat" "char-to-string" "rx-" "goto-" "when" "search-" "re-")) + (elp-instrument-package p)) + (dotimes (x ,times) + ,@body) + (elp-results) + (elp-restore-all) + (point-min) + (forward-line 20) + (delete-region (point) (point-max)) + (setq output (buffer-substring-no-properties (point-min) (point-max))) + (kill-buffer) + (delete-window) + output)) +#+END_SRC + diff --git a/tests/data.org b/tests/data.org index 403ee91..1f618ca 100644 --- a/tests/data.org +++ b/tests/data.org @@ -1,38 +1,34 @@ #+TODO: TODO TODAY NEXT STARTED IN-PROGRESS UNDERWAY WAITING SOMEDAY MAYBE CHECK | DONE CANCELED -* Test data +# Will try to open the agenda view as if it was [2017-07-05 Wed] -Rather than using my personal agenda every time I want to take a screenshot, how about this. - -Will try to open the agenda view as if it was [2017-07-05 Wed] - -** TODO [#A] Take over the universe :universe:ambition: +* TODO [#A] Take over the universe :universe:ambition: DEADLINE: <2017-07-15 Sat -1m> :PROPERTIES: :agenda-group: plans :CATEGORY: ambition :END: -*** TODO [#A] Take over the world :world: +** TODO [#A] Take over the world :world: DEADLINE: <2017-07-07 Fri> I'd like to be finished with this before the weekend... -**** TODO [#A] Skype with president of Antarctica :world:meetings: +*** TODO [#A] Skype with president of Antarctica :world:meetings: SCHEDULED: <2017-07-04 Tue 21:00> Not sure what his timezone is... -*** TODO [#B] Take over Mars +** TODO [#B] Take over Mars -**** TODO Visit Mars :space:travel:planet: +*** TODO Visit Mars :space:travel:planet: DEADLINE: <2017-09-20 Wed -3m> Ah, the red planet... -*** TODO [#C] Take over the moon +** TODO [#C] Take over the moon -**** WAITING Visit the moon :space:travel: +*** WAITING Visit the moon :space:travel: DEADLINE: <2017-08-27 Sun -2m> :LOGBOOK: - State "WAITING" from [2017-07-24 Mon 19:01] @@ -40,16 +36,16 @@ DEADLINE: <2017-08-27 Sun -2m> Just waiting on that callback from NASA... -*** TODO Practice leaping tall buildings in a single bound :personal: +** TODO Practice leaping tall buildings in a single bound :personal: SCHEDULED: <2017-07-05 Wed +2d> :PROPERTIES: :STYLE: habit :END: -*** TODO [#B] Renew membership in supervillain club +** TODO [#B] Renew membership in supervillain club DEADLINE: <2017-07-10 Mon -1w> -*** DONE [#B] Learn universal sign language +** DONE [#B] Learn universal sign language CLOSED: [2017-07-05 Wed 03:02] :PROPERTIES: :ID: 729de245-75fa-43b4-845a-57af61109485 @@ -60,58 +56,58 @@ CLOSED: [2017-07-05 Wed 03:02] CLOCK: [2017-07-05 Wed 02:00]--[2017-07-05 Wed 03:02] => 1:02 :END: -** TODO Order a pizza :food:dinner: +* TODO Order a pizza :food:dinner: SCHEDULED: <2017-07-05 Wed 18:00> :PROPERTIES: :Effort: 5 :END: -** TODO [#C] Get haircut :personal:@town: +* TODO [#C] Get haircut :personal:@town: SCHEDULED: <2017-07-05 Wed> Should probably do this before I take over the world. Want to look my best. (Not that it will matter once I'm in charge.) -** TODO [#B] Internet :bills: +* TODO [#B] Internet :bills: DEADLINE: <2017-07-21 Fri -1m> -** TODO [#A] Spaceship lease :bills:spaceship: +* TODO [#A] Spaceship lease :bills:spaceship: DEADLINE: <2017-08-01 Tue -1m> :PROPERTIES: :agenda-group: bills :END: -** TODO [#B] Fix flux capacitor :spaceship:shopping:@computer: +* TODO [#B] Fix flux capacitor :spaceship:shopping:@computer: SCHEDULED: <2017-07-05 Wed> If I don't, the frobnicator will probably fall off halfway to Mars... Gotta buy one first, though. -** Recurring +* Recurring :PROPERTIES: :agenda-group: recurring :END: -*** CHECK /r/emacs :website:Emacs: +** CHECK /r/emacs :website:Emacs: DEADLINE: <2017-07-05 Wed +1w> -*** TODO Shop for groceries :food:shopping:@town: +** TODO Shop for groceries :food:shopping:@town: SCHEDULED: <2017-07-05 Wed +1w> :PROPERTIES: :Effort: 30 :END: -*** Sunrise/sunset +** Sunrise/sunset %%(org-super-agenda--test-diary-sunrise) %%(org-super-agenda--test-diary-sunset) -** Ideas +* Ideas :PROPERTIES: :CATEGORY: ideas :END: -*** SOMEDAY Rewrite Emacs in Common Lisp :Emacs:elisp:computers:software:programming: +** SOMEDAY Rewrite Emacs in Common Lisp :Emacs:elisp:computers:software:programming: SCHEDULED: <2017-07-05 Wed> :LOGBOOK: - State "SOMEDAY" from "MAYBE" [2017-07-24 Mon 18:59] @@ -120,447 +116,9 @@ SCHEDULED: <2017-07-05 Wed> I mean, since no one has ever tried doing it before... -*** SOMEDAY Write a symphony :music: +** SOMEDAY Write a symphony :music: :PROPERTIES: :agenda-group: plans :END: I don't know when I'll get to this, so it's undated. - -* Code - -#+BEGIN_SRC elisp - (cl-defun ap/org-tweak-timestamps (&key (offset 0) epoch-ts) - "Advance all timestamps in the current buffer as if the earliest one was on today. - OFFSET changes which timestamp (in chronological order) is set to - today. Or, if EPOCH-TS is non-nil, use it as the new zero-point - for today." - (let* ((tss (->> (org-with-wide-buffer - (goto-char (point-min)) - (cl-loop while (re-search-forward org-ts-regexp-both nil t) - collect (ts-parse-org (match-string 0)))) - (-sort #'ts<))) - (epoch-ts (if epoch-ts - (ts-parse-org epoch-ts) - (nth offset tss))) - (difference-secs (ts-diff (ts-now) epoch-ts)) - (days (floor (/ difference-secs 86400)))) - (org-with-wide-buffer - (goto-char (point-min)) - (while (re-search-forward org-ts-regexp-both nil t) - (let* ((ts (ts-parse-org (match-string 0))) - (timed-p (string-match-p (rx (repeat 2 digit) ":" (repeat 2 digit) (or ">" "]")) (match-string 0))) - (type (cond ((string-prefix-p "<" (match-string 0)) 'active) - ((string-prefix-p "[" (match-string 0)) 'inactive) - (t (error "Unknown ts type")))) - (brackets (cl-ecase type - ('active (cons "<" ">")) - ('inactive (cons "[" "]")))) - (format-string (concat (car brackets) - (if timed-p - "%Y-%m-%d %a %H:%M" - "%Y-%m-%d %a") - (cdr brackets))) - (new-ts (ts-adjust 'day days ts)) - (new-ts-string (ts-format format-string new-ts))) - (replace-match new-ts-string t t nil 0)))) - (message "Tweaked from epoch: %s" (ts-format epoch-ts)))) -#+END_SRC - -#+BEGIN_SRC elisp -(org-time-string-to-absolute (org-entry-get (point) "SCHEDULED")) -#+END_SRC - - #+BEGIN_SRC elisp :results none - ;; Setup code - (require 'org-super-agenda) - (org-super-agenda-mode 1) - (require 'org-habit) - (setq org-todo-keywords - '((sequence "TODO(t!)" "TODAY(a!)" "NEXT(n!)" "STARTED(s!)" "IN-PROGRESS(p!)" "UNDERWAY(u!)" "WAITING(w@)" "SOMEDAY(o!)" "MAYBE(m!)" "|" "DONE(d@)" "CANCELED(c@)") - (sequence "CHECK(k!)" "|" "DONE(d@)") - (sequence "TO-READ(r!)" "READING(R!)" "|" "HAVE-READ(d@)") - (sequence "TO-WATCH(!)" "WATCHING(!)" "SEEN(!)"))) - (with-current-buffer "test.org" (revert-buffer)) - - (defmacro with-org-today-date (date &rest body) - "Run BODY with the `org-today' function set to return simply DATE. - DATE should be a date-time string (both date and time must be included)." - (declare (indent defun)) - `(let ((day (date-to-day ,date)) - (orig (symbol-function 'org-today))) - (unwind-protect - (progn - (fset 'org-today (lambda () day)) - ,@body) - (fset 'org-today orig)))) - #+END_SRC - -#+BEGIN_SRC elisp :results none - (defun diary-sunrise () - (let ((dss (diary-sunrise-sunset))) - (with-temp-buffer - (insert dss) - (goto-char (point-min)) - (search-forward ",") - (buffer-substring (point-min) (match-beginning 0))))) - - (defun diary-sunset () - (let ((dss (diary-sunrise-sunset)) - start end) - (with-temp-buffer - (insert dss) - (goto-char (point-min)) - (search-forward ", ") - (setq start (match-end 0)) - (search-forward " at") - (setq end (match-beginning 0)) - (goto-char start) - (capitalize-word 1) - (buffer-substring start end)))) -#+END_SRC - -*Note:* Removing tests from here as they're added to =test.el=. - - #+BEGIN_SRC elisp - - (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Time grid items in all-uppercase with RosyBrown1 foreground" - :time-grid t - :transformer (--> it - (upcase it) - (propertize it 'face '(:foreground "RosyBrown1")))) - (:name "Priority >= C items underlined, on black background" - :face (:background "black" :underline t) - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name none - :time-grid t) - (:name "Should be all-uppercase RosyBrown1 on black" - :face (:background "black" :foreground "RosyBrown1") - :transformer #'upcase - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name none - :time-grid t) - (:name none - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Items with child TODOs" - :children todo)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Items with child TODOs" - :children "CHECK")))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Today" - :time-grid t - :scheduled today - :deadline today))))) - (todo "" ((org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Today" - :time-grid today))))) - (todo "" ((org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Schedule" - :time-grid t - :date today) - (:name "Due today" - :deadline today) - (:name "Due soon" - :deadline t))))) - (todo "" ((org-agenda-overriding-header "") - (org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:scheduled (before "2017-07-06"))))) - (org-agenda nil "a"))) -#+END_SRC - -#+BEGIN_SRC elisp - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "WAITING"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-todo-list))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "SOMEDAY"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-tags-view nil "Emacs"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "CHECK"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) -;; org-search-view doesn't seem to set the todo-state property, so the matcher doesn't work - (org-search-view nil "Emacs"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:regexp ("moon" "mars")))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-search-view nil "space"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "SOMEDAY"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-agenda-list nil nil 'day))) - -#+END_SRC - -** Agenda examining - -This helps a lot. - -#+BEGIN_SRC elisp - (defun data-debug-show-string-with-properties (s) - (with-current-buffer (get-buffer-create "argh") - (erase-buffer) - (print s (current-buffer)) - - ;; Convert string reader representations to plain lists that can be set - (cl-loop for (match replace) in '(("#(" "'(") - ("#<" "'(") - (">" ")")) - do (progn - (goto-char (point-min)) - (while (search-forward match nil 'noerror) - (replace-match replace 'fixedcase 'literal)))) - - ;; Surround content in a list which `argh' is set to, then eval - ;; the buffer to do it - (goto-char (point-min)) - (insert "(setq argh (list '") - (delete-forward-char 2) - (goto-char (point-max)) - (insert "))") - - ;; Okay, sure, eval'ing the buffer is dangerous and bad and wrong. - ;; But this is the only way I can find to make this work. (Maybe - ;; `text-properties-at' could be used to get actual lists...) - (eval-buffer) - - (data-debug-show-stuff argh "argh") - ;; (switch-to-buffer (current-buffer)) - )) - - (defun data-debug-show-current-line-with-properties () - (interactive) - (data-debug-show-string-with-properties (buffer-substring (line-beginning-position) (line-end-position)))) - - (with-current-buffer "*Org Agenda*" - (data-debug-show-string-with-properties (seq-subseq (split-string (buffer-string) "\n") - 0 5))) -#+END_SRC - -** Agenda censoring - -For sharing screenshots of the agenda without revealing private data. - -#+BEGIN_SRC elisp - (defun org-agenda-sharpie () - "Censor the text of items in the agenda." - (interactive) - (let (regexp old-heading new-heading properties) - ;; Save face properties of line in agenda to reapply to changed text - (setq properties (text-properties-at (point))) - - ;; Go to source buffer - (org-with-point-at (org-find-text-property-in-string 'org-marker - (buffer-substring (line-beginning-position) - (line-end-position))) - ;; Save old heading text and ask for new text - (line-beginning-position) - (unless (org-at-heading-p) - ;; Not sure if necessary - (org-back-to-heading)) - (setq old-heading (when (looking-at org-complex-heading-regexp) - (match-string 4)))) - (setq new-heading (read-from-minibuffer "Overwrite visible heading with: ")) - (add-text-properties 0 (length new-heading) properties new-heading) - ;; Back to agenda buffer - (save-excursion - (when (and old-heading new-heading) - ;; Replace agenda text - (let ((inhibit-read-only t)) - (goto-char (line-beginning-position)) - (when (search-forward old-heading (line-end-position)) - (replace-match new-heading 'fixedcase 'literal))))))) -#+END_SRC - -** Auto grouping - - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:auto-group t))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-agenda-list nil nil 'day))) -#+END_SRC - -** Auto categories - -#+BEGIN_SRC elisp - (let ((org-super-agenda-groups - '((:auto-category t)))) - (org-agenda-list nil nil 'day)) -#+END_SRC - -** Date - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) - (last-day-of-month - ;; A hack that seems to work fine - (1+ (calendar-last-day-of-month month year))) - (target-date (format "%d-%02d-%02d" year month last-day-of-month)) - (org-super-agenda-groups - `((:deadline (before ,target-date)) - (:discard (:anything t))))) - (org-todo-list))) - - (with-org-today-date "2017-07-05 00:00" - (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) - (last-day-of-month (calendar-last-day-of-month month year)) - (target-date (format "%d-%02d-%02d" year month last-day-of-month)) - (org-super-agenda-groups - `((:deadline (before ,target-date)) - (:discard (:anything t))))) - (org-todo-list))) -#+END_SRC - -** Effort - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-super-agenda-groups - '((:effort< "0:06")))) - (org-agenda-list nil nil 'day))) -#+END_SRC - -** Misc - -*** let-plist - -I don't need this right now, but it might come in handy here or elsewhere. - -#+BEGIN_SRC elisp - (defmacro osa/let-plist (keys plist &rest body) - "`cl-destructuring-bind' without the boilerplate for plists." - ;; See https://emacs.stackexchange.com/q/22542/3871 - - ;; I really don't understand why Emacs doesn't have this already. - ;; So many things come close to it: pcase, pcase-let, map-let, - ;; cl-destructuring-bind, -let...but none of them let you simply - ;; bind all the values of a plist to variables with the same name as - ;; their keys. You always have to type the name of the key twice. - - ;; For example, compare these two forms: - - ;; (-let (((&keys :from from :to to :date date :subject subject) email)) - ;; (list from to date subject)) - - ;; (osa/let-plist (:from :to :date :subject) email - ;; (list from to date subject)) - - ;; Now, sure, sometimes you need to bind values to differently named - ;; variables. But when you don't, I know which one I prefer. - (declare (indent defun)) - (setq keys (cl-loop for key in keys - collect (intern (replace-regexp-in-string (rx bol ":") "" - (symbol-name key))))) - `(cl-destructuring-bind - (&key ,@keys &allow-other-keys) - ,plist - ,@body)) -#+END_SRC - -** Profiling - -#+BEGIN_SRC elisp :results none - (defmacro profile-it (times &rest body) - `(let (output) - (dolist (p '("org-super-agenda-" "map" "org-" "string-" "s-" "buffer-" "append" "delq" "map" "list" "car" "save-" "outline-" "delete-dups" "sort" "line-" "nth" "concat" "char-to-string" "rx-" "goto-" "when" "search-" "re-")) - (elp-instrument-package p)) - (dotimes (x ,times) - ,@body) - (elp-results) - (elp-restore-all) - (point-min) - (forward-line 20) - (delete-region (point) (point-max)) - (setq output (buffer-substring-no-properties (point-min) (point-max))) - (kill-buffer) - (delete-window) - output)) -#+END_SRC diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 8fe0e8d..adde6ab 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -343,25 +343,25 @@ RESULTS should be a list of strings as returned by (describe "(children)" (org-ql-it "without arguments" (org-ql-expect ((children)) - '("Test data" "Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas" "Code" "Misc"))) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" (org-ql-expect ((children (todo "CHECK"))) '("Recurring"))) (org-ql-it "with grandchildren query" ;; It's really cool how this works. It's so simple. (org-ql-expect ((children (children "moon"))) - '("Test data" "Take over the universe")))) + '("Take over the universe")))) (describe "(descendants)" (org-ql-it "without arguments" (org-ql-expect ((descendants)) - '("Test data" "Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas" "Code" "Misc"))) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" (org-ql-expect ((descendants (todo "CHECK"))) - '("Test data" "Recurring"))) + '("Recurring"))) (org-ql-it "with granddescendants query" (org-ql-expect ((descendants (descendants "moon"))) - '("Test data" "Take over the universe"))) + '("Take over the universe"))) (org-ql-it "with query that should not match parent" ;; This test would fail if the `descendants' predicate did not properly exclude ;; the parent heading by narrowing the buffer to begin at the first child. @@ -553,16 +553,16 @@ RESULTS should be a list of strings as returned by (describe "(path)" (org-ql-it "without arguments" (org-ql-expect ((path)) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with one argument" (org-ql-expect ((path "data")) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two matching arguments" (org-ql-expect ((path "data" "tests")) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two arguments, one matching" (org-ql-expect ((path "data" "nope")) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling")))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(planning)" @@ -734,19 +734,19 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((tags)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) (org-ql-expect ((not (tags))) - '("Test data" "Recurring" "Sunrise/sunset" "Ideas" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" (org-ql-expect ((tags "Emacs")) '("/r/emacs" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((not (tags "Emacs"))) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with 2 tags" (org-ql-expect ((tags "Emacs" "space")) '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((not (tags "Emacs" "space"))) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling")))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony")))) (describe "(tags-inherited)" @@ -754,7 +754,7 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((tags-inherited)) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) (org-ql-expect ((not (inherited-tags))) - '("Test data" "Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with a tag" (org-ql-expect ((tags-inherited "Emacs")) @@ -762,14 +762,14 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((itags "ambition")) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) (org-ql-expect ((not (tags-i "ambition"))) - '("Test data" "Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" (org-ql-expect ((itags "personal" "world")) '("Skype with president of Antarctica")) (org-ql-expect ((not (tags-inherited "personal" "world"))) ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". - '("Test data" "Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling")))) + '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(tags-local)" @@ -777,7 +777,7 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((tags-local)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) (org-ql-expect ((not (local-tags))) - '("Test data" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" (org-ql-expect ((tags-local "world")) @@ -785,13 +785,13 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((ltags "ambition")) '("Take over the universe")) (org-ql-expect ((not (tags-l "ambition"))) - '("Test data" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" (org-ql-expect ((ltags "personal" "world")) '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) (org-ql-expect ((not (tags-local "personal" "world"))) - '("Test data" "Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling")))) + '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(tags-all), (tags&)" @@ -816,7 +816,7 @@ RESULTS should be a list of strings as returned by nil) (org-ql-then (org-ql-expect ((ts :from today)) - '("Test data" "Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then @@ -830,7 +830,7 @@ RESULTS should be a list of strings as returned by '("Skype with president of Antarctica")) (org-ql-then (org-ql-expect ((ts :to today)) - '("Test data" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" (org-ql-then @@ -844,7 +844,7 @@ RESULTS should be a list of strings as returned by nil) (org-ql-then (org-ql-expect ((ts :on today)) - '("Test data" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" (org-ql-then @@ -855,7 +855,7 @@ RESULTS should be a list of strings as returned by (org-ql-it "without arguments" (org-ql-expect ((ts :type inactive)) - '("Test data" "Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" (org-ql-expect ((ts :from "2017-07-06" :type inactive)) @@ -864,7 +864,7 @@ RESULTS should be a list of strings as returned by nil) (org-ql-then (org-ql-expect ((ts-inactive :from today)) - '("Test data" "Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then @@ -873,26 +873,26 @@ RESULTS should be a list of strings as returned by (org-ql-it ":to a timestamp" (org-ql-expect ((ts :to "2019-06-10" :type inactive)) - '("Test data" "Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :to "2017-07-04" :type inactive)) 'nil) (org-ql-then (org-ql-expect ((ts-inactive :to today)) - '("Test data" "Learn universal sign language")))) + '("Learn universal sign language")))) (org-ql-it ":to a number of days" (org-ql-then (org-ql-expect ((ts-i :to 5)) - '("Test data" "Learn universal sign language")))) + '("Learn universal sign language")))) (org-ql-it ":on a timestamp" (org-ql-expect ((ts :on "2017-07-05" :type inactive)) - '("Test data" "Learn universal sign language")) + '("Learn universal sign language")) (org-ql-expect ((ts :on "2019-06-09" :type inactive)) nil) (org-ql-then (org-ql-expect ((ts-inactive :on today)) - '("Test data" "Learn universal sign language")))) + '("Learn universal sign language")))) (org-ql-it ":on a number of days" (org-ql-then @@ -903,58 +903,58 @@ RESULTS should be a list of strings as returned by (org-ql-it "without arguments" (org-ql-expect ((ts)) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :type both)) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" (org-ql-expect ((ts :from "2017-07-05")) - '("Test data" "Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :from "2017-07-05" :type both)) - '("Test data" "Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :from "2019-06-08")) nil) (org-ql-expect ((ts :from "2019-06-08" :type both)) nil) (org-ql-then (org-ql-expect ((ts :from today)) - '("Test data" "Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then (org-ql-expect ((ts :from -5)) - '("Test data" "Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" (org-ql-expect ((ts :to "2017-07-06")) - '("Test data" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :to "2017-07-06" :type both)) - '("Test data" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :to "2017-07-04")) '("Skype with president of Antarctica")) (org-ql-expect ((ts :to "2017-07-04" :type both)) '("Skype with president of Antarctica")) (org-ql-then (org-ql-expect ((ts :to today)) - '("Test data" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" (org-ql-then (org-ql-expect ((ts :to 5)) - '("Test data" "Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a timestamp" (org-ql-expect ((ts :on "2017-07-05")) - '("Test data" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :on "2017-07-05" :type both)) - '("Test data" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((ts :on "2019-06-09")) nil) (org-ql-expect ((ts :on "2019-06-09" :type both)) nil) (org-ql-then (org-ql-expect ((ts :on today)) - '("Test data" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" (org-ql-then From dadbbe4a8769a070fd78104e80dbba28c747afdd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 09:25:50 -0600 Subject: [PATCH 059/560] Tests: Allow using other data file --- tests/test-org-ql.el | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index adde6ab..ca20066 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -32,6 +32,9 @@ ;;;; Variables +(defvar org-ql-test-buffer nil + "Buffer used for running test queries.") + ;;;; Functions (defun org-ql-test-insert-result () @@ -45,9 +48,14 @@ ('org-ql--pre-process-query t) (_ nil))) (result (pcase sexp - (`(org-ql-expect ,args) (org-ql-test--format-result--ql `(org-ql org-ql-test-buffer - ,@args - :action (org-ql-test-org-get-heading)))) + (`(org-ql-expect ,args) + (org-ql-test--format-result--ql `(org-ql org-ql-test-buffer + ,@args + :action (org-ql-test-org-get-heading)))) + (`(org-ql-expect ,args ,_ :buffer ,buffer) + (org-ql-test--format-result--ql `(org-ql ,buffer + ,@args + :action (org-ql-test-org-get-heading)))) (`(org-ql . _) (org-ql-test--format-result--ql sexp)) (`(org-ql--query-preamble . _) (org-ql-test--format-result--query-preamble sexp)) (`(org-ql--pre-process-query . _) (format "'%S" (eval sexp))) @@ -87,6 +95,14 @@ (eval sexp) (user-error "Point must be after an `org-ql' form"))) +(defun org-ql-test-data-buffer (filename) + "Return buffer visiting FILENAME. +FILENAME should be a file in the \"tests\" directory." + (->> (locate-dominating-file default-directory ".git") + (expand-file-name "tests") + (expand-file-name filename) + find-file-noselect)) + ;;;; Macros (defmacro org-ql-it (description &rest body) @@ -105,12 +121,12 @@ Based on Buttercup macro `it'." ,@body)))) `(buttercup-xit ,description))) -(defmacro org-ql-expect (ql-args results) +(cl-defmacro org-ql-expect (ql-args results &key (buffer 'org-ql-test-buffer)) "Expand to `expect' test form that expects QL-ARGS to equal RESULTS. RESULTS should be a list of strings as returned by `org-ql-test-org-get-heading'." (declare (indent defun)) - `(expect (org-ql org-ql-test-buffer + `(expect (org-ql ,buffer ,@ql-args :action (org-ql-test-org-get-heading)) :to-equal ,results)) @@ -138,9 +154,7 @@ RESULTS should be a list of strings as returned by ;; For Org 9.1.9. (substring-no-properties (org-get-heading t t t t)))) - (setq org-ql-test-buffer (->> (locate-dominating-file default-directory ".git") - (expand-file-name "tests/data.org") - find-file-noselect) + (setq org-ql-test-buffer (org-ql-test-data-buffer "data.org") ;; For manual testing: ;; org-ql-test-buffer (find-file-noselect "data.org") org-ql-test-num-headings (with-current-buffer org-ql-test-buffer From 9f5bbeb3f246079dce8cbff11ef365b2a0ef2ff1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 09:27:21 -0600 Subject: [PATCH 060/560] Fix: Inherit org-file-tags Fixes #55. Closes #57. Thanks to Mikhail Skorzhinskiy (@mskorzhinskiy). --- README.org | 1 + org-ql.el | 35 +++++++++++++++++++---------------- org-ql.info | 27 +++++++++++++++------------ tests/data2.org | 16 ++++++++++++++++ tests/test-org-ql.el | 37 +++++++++++++++++++++++++++++++++---- 5 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 tests/data2.org diff --git a/README.org b/README.org index b4db8a6..e16f59c 100644 --- a/README.org +++ b/README.org @@ -392,6 +392,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. *Fixed* ++ Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) + Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to [[https://github.com/matthuszagh][Matt Huszagh]] for reporting.) + Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. + Face for done to-do keywords in =org-ql-view= buffers. (Thanks to [[https://github.com/dsdshcym][Yiming Chen]].) diff --git a/org-ql.el b/org-ql.el index 9f7d939..77de804 100644 --- a/org-ql.el +++ b/org-ql.el @@ -392,22 +392,25 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." 'org-ql-nil)) (inherited-tags (or (when org-use-tag-inheritance (save-excursion - (when (org-up-heading-safe) - (-let* (((inherited local) (org-ql--tags-at (point))) - (tags (when (or inherited local) - (cond ((and (listp inherited) - (listp local)) - (->> (append inherited local) - -non-nil -uniq)) - ((listp inherited) inherited) - ((listp local) local))))) - (cl-typecase org-use-tag-inheritance - (list (setf tags (-intersection tags org-use-tag-inheritance))) - (string (setf tags (--select (string-match org-use-tag-inheritance it) - tags)))) - (pcase org-tags-exclude-from-inheritance - ('nil tags) - (_ (-difference tags org-tags-exclude-from-inheritance))))))) + (if (org-up-heading-safe) + ;; Return parent heading's tags. + (-let* (((inherited local) (org-ql--tags-at (point))) + (tags (when (or inherited local) + (cond ((and (listp inherited) + (listp local)) + (->> (append inherited local) + -non-nil -uniq)) + ((listp inherited) inherited) + ((listp local) local))))) + (cl-typecase org-use-tag-inheritance + (list (setf tags (-intersection tags org-use-tag-inheritance))) + (string (setf tags (--select (string-match org-use-tag-inheritance it) + tags)))) + (pcase org-tags-exclude-from-inheritance + ('nil tags) + (_ (-difference tags org-tags-exclude-from-inheritance)))) + ;; Top-level heading: use file tags. + org-file-tags))) 'org-ql-nil)) (all-tags (list inherited-tags local-tags))) ;; Check caches again, because they may have been set now. diff --git a/org-ql.info b/org-ql.info index c11519c..67b883b 100644 --- a/org-ql.info +++ b/org-ql.info @@ -723,6 +723,9 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog for custom Helm commands that search certain files. *Fixed* + • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 + (https://github.com/alphapapa/org-ql/issues/55). Thanks to Mikhail + Skorzhinskiy (https://github.com/mskorzhinskiy).) • Call helm-make-source directly instead of using helm-build-sync-source macro. (Fixes #60 (https://github.com/alphapapa/org-ql/issues/60). Thanks to Matt @@ -1023,18 +1026,18 @@ Node: Agenda-like views18276 Node: Listing / acting-on results19681 Node: Changelog24283 Node: 04-pre24820 -Node: 03226633 -Node: 03127014 -Node: 0327209 -Node: 02330182 -Node: 02230408 -Node: 02130674 -Node: 0230871 -Node: 0134904 -Node: Notes35003 -Node: Comparison with Org Agenda searches35165 -Node: org-sidebar36036 -Node: License36315 +Node: 03226835 +Node: 03127216 +Node: 0327411 +Node: 02330384 +Node: 02230610 +Node: 02130876 +Node: 0231073 +Node: 0135106 +Node: Notes35205 +Node: Comparison with Org Agenda searches35367 +Node: org-sidebar36238 +Node: License36517  End Tag Table diff --git a/tests/data2.org b/tests/data2.org new file mode 100644 index 0000000..673cf7f --- /dev/null +++ b/tests/data2.org @@ -0,0 +1,16 @@ +# This file is currently used to test org-file-tags. + +#+FILETAGS: :food: + +* Fruit :fruit: + +** Blueberry + +** Strawberry + +* Vegetable :vegetable: + +** Broccoli + +** Potato + diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index ca20066..babdb87 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -760,7 +760,15 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((tags "Emacs" "space")) '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) (org-ql-expect ((not (tags "Emacs" "space"))) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony")))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + + (org-ql-it "with file tags" + (org-ql-expect ((tags "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-inherited)" @@ -783,7 +791,15 @@ RESULTS should be a list of strings as returned by '("Skype with president of Antarctica")) (org-ql-expect ((not (tags-inherited "personal" "world"))) ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". - '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + + (org-ql-it "with file tags" + (org-ql-expect ((tags-inherited "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-inherited "fruit")) + '("Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-local)" @@ -805,7 +821,15 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((ltags "personal" "world")) '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) (org-ql-expect ((not (tags-local "personal" "world"))) - '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + + (org-ql-it "with file tags" + (org-ql-expect ((tags-local "food")) + nil + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-local "fruit")) + '("Fruit") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-all), (tags&)" @@ -813,7 +837,12 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((tags-all "universe" "personal")) '("Practice leaping tall buildings in a single bound")) (org-ql-expect ((tags& "ambition" "space")) - '("Visit Mars" "Visit the moon")))) + '("Visit Mars" "Visit the moon"))) + + (org-ql-it "with file tags" + (org-ql-expect ((tags-all "food" "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(ts)" From 5b48d62e87a375e3316e7556b31b2b8ebc83a199 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 11:01:18 -0600 Subject: [PATCH 061/560] Meta: Update Makefile, makem.sh --- Makefile | 4 ++ makem.sh | 139 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 92 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index 5000738..58c5a06 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,7 @@ +# * makem.sh/Makefile --- Script to aid building and testing Emacs Lisp packages + +# This Makefile is from the makem.sh repo: . + # * Arguments # For consistency, we use only var=val options, not hyphen-prefixed options. diff --git a/makem.sh b/makem.sh index d63285c..4c739cb 100755 --- a/makem.sh +++ b/makem.sh @@ -46,6 +46,60 @@ # * Functions +function usage { + cat <. + + -s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary + directory (removing directory on exit). + -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it + on exit). Implies -s. + --auto-install Automatically install package dependencies. + -i, --install PACKAGE Install PACKAGE before running rules. + +Source files are automatically discovered from git, or may be +specified with options. + +Package dependencies are discovered from "Package-Requires" headers in +source files and from a Cask file. +EOF +} + # ** Elisp # These functions return a path to an elisp file which can be loaded @@ -113,10 +167,10 @@ EOF # ** Emacs function run_emacs { - debug "run_emacs: $emacs_command -Q --batch --load=$package_initialize_file -L \"$load_path\" $@" + debug "run_emacs: $emacs_command -Q $batch_arg --load=$package_initialize_file -L \"$load_path\" $@" if [[ $debug_load_path ]] then - debug $($emacs_command -Q --batch \ + debug $($emacs_command -Q $batch_arg \ --load=$package_initialize_file \ -L "$load_path" \ --eval "(message \"LOAD-PATH: %s\" load-path)" \ @@ -124,7 +178,7 @@ function run_emacs { fi output_file=$(mktemp) - $emacs_command -Q --batch \ + $emacs_command -Q $batch_arg \ --load=$package_initialize_file \ -L "$load_path" \ "$@" \ @@ -328,53 +382,6 @@ function ts { date "+%Y-%m-%d %H:%M:%S" } -function usage { - cat <. - - -s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary - directory (removing directory on exit). - -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it - on exit). Implies -s. - --auto-install Automatically install package dependencies. - -i, --install PACKAGE Install PACKAGE before running rules. - -Source files are automatically discovered from git, or may be -specified with options. - -Package dependencies are discovered from "Package-Requires" headers in -source files and from a Cask file. -EOF -} - # * Rules # These functions are intended to be called as rules, like a Makefile. @@ -398,6 +405,23 @@ function compile { || error "Compilation failed." } +function batch { + # Run Emacs with $batch_args and with project source and test files loaded. + verbose 1 "Executing Emacs with arguments: ${batch_args[@]}" + + run_emacs \ + $(load-files-args "${project_source_files[@]}" "${project_test_files[@]}") \ + "${batch_args[@]}" +} + +function interactive { + # Run Emacs interactively. Most useful with --sandbox and --auto-install. + unset batch_arg + run_emacs \ + $(load-files-args "${project_source_files[@]}" "${project_test_files[@]}") + batch_arg="--batch" +} + function lint { verbose 1 "Linting..." @@ -485,6 +509,7 @@ emacs_command="emacs" errors=0 verbose=0 compile=true +batch_arg="--batch" # MAYBE: Disable color if not outputting to a terminal. (OTOH, the # colorized output is helpful in CI logs, and I don't know if, @@ -659,7 +684,16 @@ fi # Run rules. for rule in "${rest[@]}" do - if type "$rule" 2>/dev/null | grep "$rule is a function" &>/dev/null + if [[ $batch ]] + then + debug "Adding batch argument: $rule" + batch_args+=("$rule") + + elif [[ $rule = batch ]] + then + # Remaining arguments are passed to Emacs. + batch=true + elif type "$rule" 2>/dev/null | grep "$rule is a function" &>/dev/null then $rule elif [[ $rule = test ]] @@ -672,6 +706,9 @@ do fi done +# The batch rule. +[[ $batch ]] && batch + if [[ $errors -gt 0 ]] then log_color red "Finished with $errors errors." From 3ce29bee46d0ff5a2091a85ef053cb1a19aa6d99 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 12:45:53 -0600 Subject: [PATCH 062/560] Meta: (test.yml) Don't count lint failure as job failure It's more valuable to see at a glance that the tests passed than to have every run indicate failure because of lint failures, especially when some of the lint failures come from package-lint issues that may be patched in the future. --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b56b721..4d96ba5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -61,6 +61,7 @@ jobs: # as failures, so linting and testing are run as separate steps. - name: Lint + continue-on-error: true run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint - name: Test From 9d15f503ba981ebdb939b33a80bc314309cf22a9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 12:58:52 -0600 Subject: [PATCH 063/560] Tidy: Use alternatives to map-put Emacs 27 marks map-put as obsolete and renames it to map-put!, which causes byte-compilation warnings (sigh...isn't that the definition of useless churn?). Of course, map-put! doesn't exist in Emacs 26, so we can't just use that. I'm beginning to think that it will never be possible to make the linting clean. --- org-ql-view.el | 2 +- org-ql.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 08babe7..72f44e8 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -312,7 +312,7 @@ update search arguments." :narrow org-ql-view-narrow :super-groups org-ql-view-super-groups :title name))) - (map-put org-ql-views name plist #'equal) + (setf (map-elt org-ql-views name nil #'equal) plist) (customize-set-variable 'org-ql-views org-ql-views) (customize-mark-to-save 'org-ql-views))) diff --git a/org-ql.el b/org-ql.el index 77de804..27ede79 100644 --- a/org-ql.el +++ b/org-ql.el @@ -477,7 +477,7 @@ Values compared with `equal'." (puthash (current-buffer) (cons (buffer-modified-tick) position-cache) org-ql-node-value-cache)) - (map-put value-cache fn new-value) + (setf (alist-get fn value-cache nil nil #'equal) new-value) (puthash position value-cache position-cache) new-value)) ;; Return nil or the non-nil value. From 16cb6cef526cc4f18e0a8f465857bd175eb55a9f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 8 Jan 2020 13:05:50 -0600 Subject: [PATCH 064/560] Tests: Declare variable --- tests/test-org-ql.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index babdb87..06253e6 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -35,6 +35,10 @@ (defvar org-ql-test-buffer nil "Buffer used for running test queries.") +(defvar org-ql-test-num-headings nil + "Total number of headings in main test data buffer. +Set at runtime by test suite.") + ;;;; Functions (defun org-ql-test-insert-result () From 1f79632372f3c97d5ec941eab50a079e2b661977 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 10 Jan 2020 07:26:22 -0600 Subject: [PATCH 065/560] Meta: Update makem.sh, test.yml --- .github/workflows/test.yml | 14 +- makem.sh | 315 ++++++++++++++++++++----------------- 2 files changed, 178 insertions(+), 151 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4d96ba5..9a9c29c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,6 +27,7 @@ name: "CI" on: pull_request: push: + # Comment out this section to enable testing of all branches. # branches: # - master @@ -46,16 +47,11 @@ jobs: - uses: actions/checkout@v2 - - name: Install sandbox script - run: | - curl -o $GITHUB_WORKSPACE/emacs-sandbox.sh \ - https://raw.githubusercontent.com/alphapapa/emacs-sandbox.sh/master/emacs-sandbox.sh - chmod +x $GITHUB_WORKSPACE/emacs-sandbox.sh - echo ::add-path::$GITHUB_WORKSPACE - echo ::set-env name=SANDBOX_DIR::$(mktemp -d) - - name: Initialize sandbox - run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --auto-install --install package-lint + run: | + SANDBOX_DIR=$(mktemp -d) || exit 1 + echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR + ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --auto-install --install package-lint # The "all" rule is not used, because it treats compilation warnings # as failures, so linting and testing are run as separate steps. diff --git a/makem.sh b/makem.sh index 4c739cb..4cdf914 100755 --- a/makem.sh +++ b/makem.sh @@ -21,13 +21,11 @@ # occur. With increasing verbosity levels, more detail gives positive # feedback. Output is colored by default to make reading easy. -# When desired, emacs-sandbox.sh can be used as a backend, which -# allows package dependencies to be installed automatically into a -# clean Emacs "sandbox" configuration without affecting the -# developer's personal configuration. This is especially helpful when +# The script can run Emacs with the developer's local Emacs +# configuration, or with a clean, "sandbox" configuration that can be +# optionally removed afterward. This is especially helpful when # upstream dependencies may have released new versions that differ -# from those installed in the developer's personal configuration. See -# . +# from those installed in the developer's personal configuration. # * License: @@ -63,18 +61,17 @@ Rules: test-buttercup Run Buttercup tests. test-ert Run ERT tests. - These are especially useful with --sandbox: - - batch Run Emacs in batch mode, loading project source and test files - automatically, with remaining args (after "--") passed to Emacs. - interactive Run Emacs interactively, loading project source and test files - automatically. + batch Run Emacs in batch mode, loading project source and test files + automatically, with remaining args (after "--") passed to Emacs. + interactive Run Emacs interactively, loading project source and test files + automatically. Options: -d, --debug Print debug info. -h, --help I need somebody! -v, --verbose Increase verbosity, up to -vv. - --debug-load-path Print load-path. + + --debug-load-path Print load-path from inside Emacs. -f FILE, --file FILE Check FILE in addition to discovered files. @@ -82,10 +79,7 @@ Options: -C, --no-compile Don't compile files automatically. Sandbox options: - These require emacs-sandbox.sh to be on your PATH. Find it at - . - - -s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary + -s, --sandbox Run Emacs with an empty config in a temporary directory (removing directory on exit). -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it on exit). Implies -s. @@ -93,10 +87,8 @@ Sandbox options: -i, --install PACKAGE Install PACKAGE before running rules. Source files are automatically discovered from git, or may be -specified with options. - -Package dependencies are discovered from "Package-Requires" headers in -source files and from a Cask file. +specified with options. Package dependencies are discovered from +"Package-Requires" headers in source files and from a Cask file. EOF } @@ -156,8 +148,8 @@ function elisp-package-initialize-file { (require 'package) (setq package-archives (list (cons "gnu" "https://elpa.gnu.org/packages/") (cons "melpa" "https://melpa.org/packages/") - (cons "melpa-stable" "https://stable.melpa.org/packages/") - (cons "org" "https://orgmode.org/elpa/"))) + (cons "melpa-stable" "https://stable.melpa.org/packages/"))) +$elisp_org_package_archive (package-initialize) (setq load-prefer-newer t) EOF @@ -167,30 +159,39 @@ EOF # ** Emacs function run_emacs { - debug "run_emacs: $emacs_command -Q $batch_arg --load=$package_initialize_file -L \"$load_path\" $@" - if [[ $debug_load_path ]] - then - debug $($emacs_command -Q $batch_arg \ - --load=$package_initialize_file \ - -L "$load_path" \ - --eval "(message \"LOAD-PATH: %s\" load-path)" \ - 2>&1) - fi + # NOTE: The sandbox args need to come before the package + # initialization so Emacs will use the sandbox's packages. + local emacs_command=( + "${emacs_command[@]}" + -Q + "${args_sandbox[@]}" + -l $package_initialize_file + $arg_batch + -L "$load_path" + ) - output_file=$(mktemp) - $emacs_command -Q $batch_arg \ - --load=$package_initialize_file \ - -L "$load_path" \ - "$@" \ - &>$output_file + # Show debug message with load-path from inside Emacs. + [[ $debug_load_path ]] \ + && debug $("${emacs_command[@]}" \ + --batch \ + --eval "(message \"LOAD-PATH: %s\" load-path)" \ + 2>&1) + # Set output file. + output_file=$(mktemp) || die "Unable to make output file." + paths_temp+=("$output_file") + + # Run Emacs. + debug "run_emacs: ${emacs_command[@]} $@ &>\"$output_file\"" + "${emacs_command[@]}" "$@" &>"$output_file" + + # Check exit code and output. exit=$? - [[ $exit != 0 ]] && debug "Emacs exited non-zero: $exit" - if [[ $verbose -gt 1 || $exit != 0 ]] - then - cat $output_file - fi - rm -f $output_file + [[ $exit != 0 ]] \ + && debug "Emacs exited non-zero: $exit" + + [[ $verbose -gt 1 || $exit != 0 ]] \ + && cat $output_file return $exit } @@ -210,27 +211,27 @@ function batch-byte-compile { # ** Files -function project-elisp-files { +function files-project-elisp { # Echo list of Elisp files in project. - git ls-files 2>/dev/null | egrep "\.el$" | exclude-files + git ls-files 2>/dev/null | egrep "\.el$" | filter-files-exclude } -function project-source-files { +function files-project-source { # Echo list of Elisp files that are not tests. - project-elisp-files | egrep -v "$test_files_regexp" | feature-files + files-project-elisp | egrep -v "$test_files_regexp" | filter-files-feature } -function project-test-files { +function files-project-test { # Echo list of Elisp test files. - project-elisp-files | egrep "$test_files_regexp" + files-project-elisp | egrep "$test_files_regexp" } -function exclude-files { +function filter-files-exclude { # Filter out paths (STDIN) which should be excluded by default. egrep -v "(/\.cask/|-autoloads.el|.dir-locals)" } -function feature-files { +function filter-files-feature { # Read paths on STDIN and echo ones that (provide 'a-feature). while read path do @@ -240,7 +241,7 @@ function feature-files { done } -function load-files-args { +function args-load-files { # For file in $@, echo "--load $file". for file in "$@" do @@ -248,17 +249,9 @@ function load-files-args { done } -function files_args { - # For file in STDIN, echo "$file". - while read file - do - printf -- '%q ' "$file" - done -} - function test-files-p { - # Return 0 if $project_test_files is non-empty. - [[ "${project_test_files[@]}" ]] + # Return 0 if $files_project_test is non-empty. + [[ "${files_project_test[@]}" ]] } function buttercup-tests-p { @@ -266,7 +259,7 @@ function buttercup-tests-p { test-files-p || die "No tests found." debug "Checking for Buttercup tests..." - grep "(require 'buttercup)" "${project_test_files[@]}" &>/dev/null + grep "(require 'buttercup)" "${files_project_test[@]}" &>/dev/null } function ert-tests-p { @@ -277,14 +270,14 @@ function ert-tests-p { # We check for this rather than "(require 'ert)", because ERT may # already be loaded in Emacs and might not be loaded with # "require" in a test file. - grep "(ert-deftest" "${project_test_files[@]}" &>/dev/null + grep "(ert-deftest" "${files_project_test[@]}" &>/dev/null } function dependencies { # Echo list of package dependencies. # Search package headers. - egrep '^;; Package-Requires: ' $(project-source-files) $(project-test-files) \ + egrep '^;; Package-Requires: ' $(files-project-source) $(files-project-test) \ | egrep -o '\([^([:space:]][^)]*\)' \ | egrep -o '^[^[:space:])]+' \ | sed -r 's/\(//g' \ @@ -298,12 +291,70 @@ function dependencies { fi } +# ** Sandbox + +function sandbox { + # Initialize sandbox. + + # *** Sandbox arguments + + # Check or make user-emacs-directory. + if [[ $sandbox_dir ]] + then + # Directory given as argument: ensure it exists. + [[ -d $sandbox_dir ]] || die "Directory doesn't exist: $sandbox_dir" + else + # Not given: make temp directory, and delete it on exit. + local sandbox_dir=$(mktemp -d) || die "Unable to make sandbox dir." + paths_temp+=("$sandbox_dir") + fi + + # Make argument to load init file if it exists. + init_file="$sandbox_dir/init.el" + [[ -r $init_file ]] \ + && local args_load_init_file=(--load "$init_file") + + # Set sandbox args. This is a global variable used by the run_emacs function. + args_sandbox=( + --eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))" + --eval "(setq user-init-file (file-truename \"$init_file\"))" + "${args_load_init_file[@]}" + ) + + # Add package-install arguments for dependencies. + if [[ $auto_install ]] + then + local deps=($(dependencies)) + debug "Installing dependencies: ${deps[@]}" + + for package in "${deps[@]}" + do + args_sandbox_package_install+=(--eval "(package-install '$package)") + done + fi + + # *** Install packages into sandbox + + if [[ ${args_sandbox_package_install[@]} ]] + then + # Initialize the sandbox (installs packages once rather than for every rule). + debug "Initializing sandbox..." + + run_emacs \ + --eval "(package-refresh-contents)" \ + "${args_sandbox_package_install[@]}" \ + || die "Unable to initialize sandbox." + fi + + debug "Sandbox initialized." +} + # ** Utility function cleanup { - # Remove temporary paths (${temp_paths[@]}). + # Remove temporary paths (${paths_temp[@]}). - for path in "${temp_paths[@]}" + for path in "${paths_temp[@]}" do if [[ $debug ]] then @@ -398,28 +449,28 @@ function compile { unset compile # Only compile once. verbose 1 "Compiling..." - debug "Byte-compile files: ${project_byte_compile_files[@]}" + debug "Byte-compile files: ${files_project_byte_compile[@]}" - batch-byte-compile "${project_byte_compile_files[@]}" \ + batch-byte-compile "${files_project_byte_compile[@]}" \ && success "Compiling finished without errors." \ || error "Compilation failed." } function batch { - # Run Emacs with $batch_args and with project source and test files loaded. - verbose 1 "Executing Emacs with arguments: ${batch_args[@]}" + # Run Emacs with $args_batch and with project source and test files loaded. + verbose 1 "Executing Emacs with arguments: ${args_batch[@]}" run_emacs \ - $(load-files-args "${project_source_files[@]}" "${project_test_files[@]}") \ - "${batch_args[@]}" + $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") \ + "${args_batch[@]}" } function interactive { # Run Emacs interactively. Most useful with --sandbox and --auto-install. - unset batch_arg + unset arg_batch run_emacs \ - $(load-files-args "${project_source_files[@]}" "${project_test_files[@]}") - batch_arg="--batch" + $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") + arg_batch="--batch" } function lint { @@ -434,11 +485,11 @@ function lint-checkdoc { verbose 1 "Linting checkdoc..." local checkdoc_file="$(elisp-checkdoc-file)" - temp_paths+=("$checkdoc_file") + paths_temp+=("$checkdoc_file") run_emacs \ --load="$checkdoc_file" \ - "${project_source_files[@]}" \ + "${files_project_source[@]}" \ && success "Linting checkdoc finished without errors." \ || error "Linting checkdoc failed." } @@ -447,7 +498,7 @@ function lint-compile { verbose 1 "Linting compilation..." compile_error_on_warn=true - batch-byte-compile "${project_byte_compile_files[@]}" \ + batch-byte-compile "${files_project_byte_compile[@]}" \ && success "Linting compilation finished without errors." \ || error "Linting compilation failed." unset compile_error_on_warn @@ -459,7 +510,7 @@ function lint-package { run_emacs \ --load package-lint \ --funcall package-lint-batch-and-exit \ - "${project_source_files[@]}" \ + "${files_project_source[@]}" \ && success "Linting package finished without errors." \ || error "Linting package failed." } @@ -478,7 +529,7 @@ function test-buttercup { verbose 1 "Running Buttercup tests..." local buttercup_file="$(elisp-buttercup-file)" - temp_paths+=("$buttercup_file") + paths_temp+=("$buttercup_file") run_emacs \ --load buttercup \ @@ -493,10 +544,10 @@ function test-ert { compile || die verbose 1 "Running ERT tests..." - debug "Test files: ${project_test_files[@]}" + debug "Test files: ${files_project_test[@]}" run_emacs \ - $(load-files-args "${project_test_files[@]}") \ + $(args-load-files "${files_project_test[@]}") \ -f ert-run-tests-batch-and-exit \ && success "ERT tests finished without errors." \ || error "ERT tests failed." @@ -505,11 +556,12 @@ function test-ert { # * Defaults test_files_regexp='^(tests?|t)/' -emacs_command="emacs" + +emacs_command=("emacs") errors=0 verbose=0 compile=true -batch_arg="--batch" +arg_batch="--batch" # MAYBE: Disable color if not outputting to a terminal. (OTOH, the # colorized output is helpful in CI logs, and I don't know if, @@ -549,22 +601,36 @@ COLOR_purple='\e[0;35m' COLOR_cyan='\e[0;36m' COLOR_white='\e[0;37m' +# ** Package system args + +args_package_archives=( + --eval "(add-to-list 'package-archives '(\"gnu\" . \"https://elpa.gnu.org/packages/\") t)" + --eval "(add-to-list 'package-archives '(\"melpa\" . \"https://melpa.org/packages/\") t)" +) + +args_org_package_archives=( + --eval "(add-to-list 'package-archives '(\"org\" . \"https://orgmode.org/elpa/\") t)" +) + +args_package_init=( + --eval "(package-initialize)" +) + +elisp_org_package_archive="(add-to-list 'package-archives '(\"org\" . \"https://orgmode.org/elpa/\") t)" + # * Project files # MAYBE: Option to not byte-compile test files. (OTOH, byte-compiling reveals many # errors that would otherwise go unnoticed, so it's worth it to fix the warnings.) -project_source_files=($(project-source-files)) -project_test_files=($(project-test-files)) -project_byte_compile_files=("${project_source_files[@]}" "${project_test_files[@]}") - -package_initialize_file="$(elisp-package-initialize-file)" -temp_paths+=("$package_initialize_file") +files_project_source=($(files-project-source)) +files_project_test=($(files-project-test)) +files_project_byte_compile=("${files_project_source[@]}" "${files_project_test[@]}") # * Args args=$(getopt -n "$0" \ - -o dhi:sS:vf:C \ - -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox,sandbox-dir: \ + -o dhi:sS:vf:CO \ + -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox,sandbox-dir: \ -- "$@") \ || { usage; exit 1; } eval set -- "$args" @@ -588,7 +654,7 @@ do ;; -i|--install) shift - sandbox_install_packages_args+=(--install "$1") + args_sandbox_package_install+=(--eval "(package-install '$1)") ;; -s|--sandbox) sandbox=true @@ -606,6 +672,9 @@ do project_source_files+=("$1") project_byte_compile_files+=("$1") ;; + -O|--no-org-repo) + unset elisp_org_package_archive + ;; --no-color) unset color ;; @@ -626,60 +695,22 @@ done debug "ARGS: $args" debug "Remaining args: ${rest[@]}" +# Set package elisp (which depends on --no-org-repo arg). +package_initialize_file="$(elisp-package-initialize-file)" +paths_temp+=("$package_initialize_file") + # * Main trap cleanup EXIT INT TERM -if ! [[ ${project_source_files[@]} ]] +if ! [[ ${files_project_source[@]} ]] then error "No files specified and not in a git repo." exit 1 fi -if [[ $sandbox ]] -then - # Setup sandbox. - type emacs-sandbox.sh &>/dev/null || die "emacs-sandbox.sh not found." - - if ! [[ $sandbox_dir ]] - then - # No sandbox dir specified: make temp dir and remove it on exit. - sandbox_dir=$(mktemp -d) || die "Unable to make temp dir." - temp_paths+=("$sandbox_dir") - fi - - sandbox_basic_args=( - -d "$sandbox_dir" - ) - [[ $debug ]] && sandbox_basic_args+=(--debug) - - if [[ $auto_install ]] - then - # Add dependencies to package install list. - deps=($(dependencies)) - debug "Installing dependencies: ${deps[@]}" - - for package in "${deps[@]}" - do - sandbox_install_packages_args+=(--install $package) - done - fi - - if [[ ${sandbox_install_packages_args[@]} ]] - then - # Initialize the sandbox (installs packages once rather than for every rule). - emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} ${sandbox_install_packages_args[@]} -- " - debug "Initializing sandbox..." - - run_emacs || die "Unable to initialize sandbox." - fi - - # After the sandbox is initialized and packages are installed, set the command - # to prevent the package lists from being refreshed on each invocation. - emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]} --no-refresh-packages -- " - - debug "Sandbox initialized." -fi +# Initialize sandbox. +[[ $sandbox ]] && sandbox # Run rules. for rule in "${rest[@]}" @@ -687,13 +718,13 @@ do if [[ $batch ]] then debug "Adding batch argument: $rule" - batch_args+=("$rule") + args_batch+=("$rule") elif [[ $rule = batch ]] then # Remaining arguments are passed to Emacs. batch=true - elif type "$rule" 2>/dev/null | grep "$rule is a function" &>/dev/null + elif type -t "$rule" 2>/dev/null | grep function &>/dev/null then $rule elif [[ $rule = test ]] From c4f9a58fd66c375b54befec4d6159be4135df7e6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 10 Jan 2020 10:21:55 -0600 Subject: [PATCH 066/560] Docs: Improve ToCs --- README.org | 71 +++++++++++++++++++---------------- org-ql.info | 106 ++++++++++++++++++++++++++-------------------------- 2 files changed, 92 insertions(+), 85 deletions(-) diff --git a/README.org b/README.org index e16f59c..1438e84 100644 --- a/README.org +++ b/README.org @@ -14,14 +14,17 @@ It includes three libraries: The =org-ql= library is flexible and may be used as :PROPERTIES: :TOC: this :END: - - [[#screenshots][Screenshots]] - - [[#installation][Installation]] - - [[#usage][Usage]] - - [[#commands][Commands]] - - [[#queries][Queries]] - - [[#functions--macros][Functions / Macros]] - - [[#changelog][Changelog]] - - [[#notes][Notes]] +- [[#screenshots][Screenshots]] +- [[#installation][Installation]] +- [[#usage][Usage]] + - [[#commands][Commands]] + - [[#queries][Queries]] + - [[#non-sexp-query-syntax][Non-sexp query syntax]] + - [[#predicates][Predicates]] + - [[#datetime-predicates][Date/time predicates]] + - [[#functions--macros][Functions / Macros]] +- [[#changelog][Changelog]] +- [[#notes][Notes]] * Screenshots @@ -57,22 +60,13 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: #+END_SRC * Usage +:CONTENTS: +- [[#commands][Commands]] +- [[#queries][Queries]] +- [[#functions--macros][Functions / Macros]] +:END: -These commands and functions are included: - -+ *Showing an agenda-like view:* - - ~org-ql-search~ (command) - - ~org-ql-view~ (command) - - ~org-ql-view-sidebar~ (command) - - ~org-ql-block~ (agenda block function) -+ *Showing a tree in a buffer:* - - ~org-ql-sparse-tree~ (command) -+ *Showing results with Helm*: - - ~helm-org-ql~ (command) -+ *Returning a list of matches or acting on them:* - - ~org-ql~ (macro) - - ~org-ql-select~ (function) - - ~org-ql-query~ (function) +# These links work on GitHub's Org renderer but not in Org. Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -84,6 +78,16 @@ Lisp code examples are in [[examples.org]]. :TOC: ignore-children :END: ++ *Showing an agenda-like view:* + - [[#org-ql-search][org-ql-search]] (command) + - [[#org-ql-view][org-ql-view]] (command) + - [[#org-ql-view-sidebar][org-ql-view-sidebar]] (command) + - [[#org-ql-view-recent-items][org-ql-view-recent-items]] (command) ++ *Showing a tree in a buffer:* + - [[#org-ql-sparse-tree][org-ql-sparse-tree]] (command) ++ *Showing results with Helm*: + - [[#helm-org-ql][helm-org-ql]] (command) + *** org-ql-search /Note: This command supports both sexp queries and [[#non-sexp-query-syntax][non-sexp queries]]./ @@ -139,6 +143,11 @@ Show a sparse tree for ~QUERY~ in ~BUFFER~ and return number of results. The tr ~QUERY~ is an ~org-ql~ query sexp (quoted, since this is a function). ~BUFFER~ defaults to the current buffer. When ~KEEP-PREVIOUS~ is non-nil (interactively, with prefix), the outline is not reset to the overview state before finding matches, which allows stacking calls to this command. Runs ~org-occur-hook~ after making the sparse tree. ** Queries +:CONTENTS: +- [[#non-sexp-query-syntax][Non-sexp query syntax]] +- [[#predicates][Predicates]] +- [[#datetime-predicates][Date/time predicates]] +:END: An =org-ql= query is a lisp form which may contain arbitrary lisp forms, as well as certain built-in predicates. It is byte-compiled into a predicate function which is tested with point on each heading in an Org buffer; when it returns non-nil, the heading matches the query. @@ -147,9 +156,6 @@ An =org-ql= query is a lisp form which may contain arbitrary lisp forms, as well + Standard numeric comparator function symbols (~<~, ~<=~, ~>~, ~>=~, ~=~ ) need not be quoted when passed as an argument to predicates which accept them. The resemblance to infix notation is coincidental. *** Non-sexp query syntax -:PROPERTIES: -:TOC: ignore -:END: The command =org-ql-search= also accepts, and the command =helm-org-ql= only accepts, an alternative, non-sexp query syntax. The syntax is simple, and a few examples of queries in both syntaxes should suffice. By default, when multiple predicates are used, they are combined with boolean =and=. @@ -170,9 +176,6 @@ The command =org-ql-search= also accepts, and the command =helm-org-ql= only acc Note that the =priority= predicate does not support comparators in the non-sexp syntax, so multiple priorities should be passed instead, as seen in the last example. *** Predicates -:PROPERTIES: -:TOC: ignore -:END: Arguments are listed next to predicate names, where applicable. @@ -204,9 +207,6 @@ Arguments are listed next to predicate names, where applicable. + =todo (&optional keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). *** Date/time predicates -:PROPERTIES: -:TOC: ignore -:END: All of these predicates take optional keyword arguments ~:from~, ~:to:~, and ~:on~: @@ -237,6 +237,13 @@ The following predicates, in addition to the keyword arguments, can also take a :TOC: ignore-children :END: +- [[#agenda-like-views][Agenda-like views]] + - [[#function-org-ql-block][Function: org-ql-block]] +- [[#listing--acting-on-results][Listing / acting-on results]] + - [[#function-org-ql-select][Function: org-ql-select]] + - [[#function-org-ql-query][Function: org-ql-query]] + - [[#macro-org-ql][Macro: org-ql]] + *** Agenda-like views **** Function: ~org-ql-block~ diff --git a/org-ql.info b/org-ql.info index 67b883b..43725a7 100644 --- a/org-ql.info +++ b/org-ql.info @@ -93,7 +93,8 @@ File: README.info, Node: Contents, Next: Screenshots, Prev: Top, Up: Top ********** • • • - • • • • • + • • + • • • • • •  File: README.info, Node: Screenshots, Next: Installation, Prev: Contents, Up: Top @@ -145,22 +146,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top 4 Usage ******* -These commands and functions are included: - - • *Showing an agenda-like view:* - • ‘org-ql-search’ (command) - • ‘org-ql-view’ (command) - • ‘org-ql-view-sidebar’ (command) - • ‘org-ql-block’ (agenda block function) - • *Showing a tree in a buffer:* - • ‘org-ql-sparse-tree’ (command) - • *Showing results with Helm*: - • ‘helm-org-ql’ (command) - • *Returning a list of matches or acting on them:* - • ‘org-ql’ (macro) - • ‘org-ql-select’ (function) - • ‘org-ql-query’ (function) - + • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -178,6 +164,16 @@ File: README.info, Node: Commands, Next: Queries, Up: Usage 4.1 Commands ============ + • *Showing an agenda-like view:* + • (command) + • (command) + • (command) + • (command) + • *Showing a tree in a buffer:* + • (command) + • *Showing results with Helm*: + • (command) + * Menu: * org-ql-search:: @@ -298,10 +294,11 @@ File: README.info, Node: Queries, Next: Functions / Macros, Prev: Commands, 4.2 Queries =========== -An org-ql query is a lisp form which may contain arbitrary lisp forms, -as well as certain built-in predicates. It is byte-compiled into a -predicate function which is tested with point on each heading in an Org -buffer; when it returns non-nil, the heading matches the query. + • • • + An org-ql query is a lisp form which may contain arbitrary lisp +forms, as well as certain built-in predicates. It is byte-compiled into +a predicate function which is tested with point on each heading in an +Org buffer; when it returns non-nil, the heading matches the query. *Notes:* • Bare strings like ‘"string"’ are automatically converted to @@ -511,6 +508,9 @@ File: README.info, Node: Functions / Macros, Prev: Queries, Up: Usage 4.3 Functions / Macros ====================== + • + • • + • • • * Menu: * Agenda-like views:: @@ -1006,38 +1006,38 @@ GPLv3 Tag Table: Node: Top225 Node: Contents1367 -Node: Screenshots1515 -Node: Installation1633 -Node: Quelpa2271 -Node: Usage2714 -Node: Commands3624 -Node: org-ql-search3853 -Node: helm-org-ql5501 -Node: org-ql-view5913 -Node: org-ql-view-sidebar6111 -Node: org-ql-view-recent-items6467 -Node: org-ql-sparse-tree6951 -Node: Queries7751 -Node: Non-sexp query syntax8593 -Node: Predicates10292 -Node: Date/time predicates15454 -Node: Functions / Macros18089 -Node: Agenda-like views18276 -Node: Listing / acting-on results19681 -Node: Changelog24283 -Node: 04-pre24820 -Node: 03226835 -Node: 03127216 -Node: 0327411 -Node: 02330384 -Node: 02230610 -Node: 02130876 -Node: 0231073 -Node: 0135106 -Node: Notes35205 -Node: Comparison with Org Agenda searches35367 -Node: org-sidebar36238 -Node: License36517 +Node: Screenshots1541 +Node: Installation1659 +Node: Quelpa2297 +Node: Usage2740 +Node: Commands3064 +Node: org-ql-search3537 +Node: helm-org-ql5185 +Node: org-ql-view5597 +Node: org-ql-view-sidebar5795 +Node: org-ql-view-recent-items6151 +Node: org-ql-sparse-tree6635 +Node: Queries7435 +Node: Non-sexp query syntax8296 +Node: Predicates9995 +Node: Date/time predicates15157 +Node: Functions / Macros17792 +Node: Agenda-like views18025 +Node: Listing / acting-on results19430 +Node: Changelog24032 +Node: 04-pre24569 +Node: 03226584 +Node: 03126965 +Node: 0327160 +Node: 02330133 +Node: 02230359 +Node: 02130625 +Node: 0230822 +Node: 0134855 +Node: Notes34954 +Node: Comparison with Org Agenda searches35116 +Node: org-sidebar35987 +Node: License36266  End Tag Table From fc536cafd6c09ba48acb99dd16b2a437ccd705f1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 13 Jan 2020 20:24:14 -0600 Subject: [PATCH 067/560] Tests: (org-ql-test-show-result) Fix symbol --- tests/test-org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 06253e6..2d1e6ed 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -92,7 +92,7 @@ Set at runtime by test suite.") (if-let* ((sexp (elisp--preceding-sexp)) (sexp (pcase sexp (`(org-ql . ,_) (setf (car sexp) 'org-ql-agenda)) - (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-select org-ql-test-buffer + (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-search org-ql-test-buffer ',@ql-args))) (_ nil)))) From 22c0b37bbe72ae7fd368114658165ca27edb26b6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 16 Jan 2020 06:21:49 -0600 Subject: [PATCH 068/560] Notes: Add idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index acc514b..58efcf3 100644 --- a/notes.org +++ b/notes.org @@ -6,6 +6,10 @@ Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. +** TODO [#A] Org block to insert results of queries with links to entries + +[2020-01-16 Thu 06:20] This idea just came to me when I was thinking about using the search-based paradigm vs. outline-based. This would allow both, e.g. some kind of =#+BEGIN_QUERY= block that would update when =C-c C-c= is pressed on it. + ** TODO [#A] Outline path in buffers-files arg :PROPERTIES: :ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 From f42bc4019d31a1475cceb50854271f42e5cc81c6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 16 Jan 2020 09:58:36 -0600 Subject: [PATCH 069/560] Notes: Add note about direx --- notes.org | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/notes.org b/notes.org index 58efcf3..61522a5 100644 --- a/notes.org +++ b/notes.org @@ -465,6 +465,14 @@ Another idea for it is to simply store the element from =org-element-headline-pa The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. +*** Prior art + +**** magit-section + +**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] + +Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. + *** Code idea Inserting items into a view could look something like this: From 0a7e4f349ff40ee9befe903be04f04703363c4c0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 18 Jan 2020 20:34:13 -0600 Subject: [PATCH 070/560] Add: (org-ql-view-refresh) Message on refresh Closes #71. Thanks to @xeijin. Squashed commit of the following: commit edac9c696061aba2a429abb8d61238fa37e28418 Author: Adam Porter Date: Sat Jan 18 20:24:28 2020 -0600 Adjust message, indentation, add changelog entry commit 6a263e34ff1d1fac00b7061282fcec39f1d619b3 Author: xeijin Date: Fri Jan 3 19:08:10 2020 +0000 removing view title commit fc37e3f1460cefe0f396f3f8033372a9d40c6107 Author: xeijin Date: Mon Dec 9 22:47:00 2019 +0000 confirmation message for org-ql-view-refresh In keeping with the message displayed by `g` when refreshing an org-agenda buffer - if nothing has changed in an `org-ql` buffer it can sometimes be difficult to determine if the refresh took place at all. --- README.org | 1 + org-ql-view.el | 3 ++- org-ql.info | 26 ++++++++++++++------------ 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 1438e84..abb5489 100644 --- a/README.org +++ b/README.org @@ -397,6 +397,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience - Alias =r= for =regexp= predicate. (Thanks to [[https://github.com/tumashu][Feng Shu]].) + Info manual. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. ++ Display a message when views are refreshed. (Thanks to [[https://github.com/xeijin][xeijin]].) *Fixed* + Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) diff --git a/org-ql-view.el b/org-ql-view.el index 72f44e8..42cf1fe 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -300,7 +300,8 @@ update search arguments." (goto-char (point-min)) (or (when (search-forward current-line nil t) (beginning-of-line)) - (goto-char old-pos)))) + (goto-char old-pos)) + (message "View refreshed"))) (defun org-ql-view-save () "Save current `org-ql-search' buffer to `org-ql-views'." diff --git a/org-ql.info b/org-ql.info index 43725a7..3254983 100644 --- a/org-ql.info +++ b/org-ql.info @@ -721,6 +721,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog • Function ‘helm-org-ql-source’, which returns a Helm source that searches given buffers/files with ‘helm-org-ql’. It can be used for custom Helm commands that search certain files. + • Display a message when views are refreshed. (Thanks to xeijin + (https://github.com/xeijin).) *Fixed* • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 @@ -1026,18 +1028,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03226584 -Node: 03126965 -Node: 0327160 -Node: 02330133 -Node: 02230359 -Node: 02130625 -Node: 0230822 -Node: 0134855 -Node: Notes34954 -Node: Comparison with Org Agenda searches35116 -Node: org-sidebar35987 -Node: License36266 +Node: 03226689 +Node: 03127070 +Node: 0327265 +Node: 02330238 +Node: 02230464 +Node: 02130730 +Node: 0230927 +Node: 0134960 +Node: Notes35059 +Node: Comparison with Org Agenda searches35221 +Node: org-sidebar36092 +Node: License36371  End Tag Table From b3601cf0aec26d4fffc2454ecc72b557dce10082 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 18 Jan 2020 22:20:52 -0600 Subject: [PATCH 071/560] Add: (org-ql-block) Respect Org Agenda restrictions Fixes #84. Thanks to Ihor Radchenko (@yantar92) for reporting. --- README.org | 1 + org-ql-search.el | 50 +++++++++++++++++++++++++++++++----------------- org-ql.info | 26 +++++++++++++------------ 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/README.org b/README.org index abb5489..aa482e0 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Info manual. + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. + Display a message when views are refreshed. (Thanks to [[https://github.com/xeijin][xeijin]].) ++ Respect Org Agenda restriction in =org-ql-block=. (Thanks to [[https://github.com/yantar92][Ihor Radchenko]] for reporting.) *Fixed* + Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) diff --git a/org-ql-search.el b/org-ql-search.el index f79b254..fab0e95 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -231,24 +231,38 @@ function `org-agenda-files'. Inserts a newline after the block. If `org-ql-block-header' is non-nil, it is used as the header string for the block, otherwise a the header is formed automatically from the query." - (when-let* ((from (org-agenda-files nil 'ifmode)) - (items (org-ql-select from query - :action 'element-with-markers))) - ;; Not sure if calling the prepare function is necessary, but let's follow the pattern. - (org-agenda-prepare) - ;; FIXME: `org-agenda--insert-overriding-header' is from an Org version newer than - ;; I'm using. Should probably declare it as a minimum Org version after upgrading. - ;; (org-agenda--insert-overriding-header (or org-ql-block-header (org-ql-agenda--header-line-format from query))) - (insert (org-add-props (or org-ql-block-header (org-ql-view--header-line-format from query)) - nil 'face 'org-agenda-structure) "\n") - ;; Calling `org-agenda-finalize' should be unnecessary, because in a "series" agenda, - ;; `org-agenda-multi' is bound non-nil, in which case `org-agenda-finalize' does nothing. - ;; But we do call `org-agenda-finalize-entries', which allows `org-super-agenda' to work. - (->> items - (-map #'org-ql-view--format-element) - org-agenda-finalize-entries - insert) - (insert "\n"))) + (let (narrow-p old-beg old-end) + (when-let* ((from (pcase org-agenda-overriding-restriction + ('nil (org-agenda-files nil 'ifmode)) + ('file (get 'org-agenda-files 'org-restrict)) + ('subtree (prog1 org-agenda-restrict + (with-current-buffer org-agenda-restrict + ;; Narrow the buffer; remember to widen it later. + (setf old-beg (point-min) old-end (point-max) + narrow-p t) + (narrow-to-region org-agenda-restrict-begin org-agenda-restrict-end)))))) + (items (org-ql-select from query + :action 'element-with-markers + :narrow narrow-p))) + (when narrow-p + ;; Restore buffer's previous restrictions. + (with-current-buffer from + (narrow-to-region old-beg old-end))) + ;; Not sure if calling the prepare function is necessary, but let's follow the pattern. + (org-agenda-prepare) + ;; FIXME: `org-agenda--insert-overriding-header' is from an Org version newer than + ;; I'm using. Should probably declare it as a minimum Org version after upgrading. + ;; (org-agenda--insert-overriding-header (or org-ql-block-header (org-ql-agenda--header-line-format from query))) + (insert (org-add-props (or org-ql-block-header (org-ql-view--header-line-format from query)) + nil 'face 'org-agenda-structure) "\n") + ;; Calling `org-agenda-finalize' should be unnecessary, because in a "series" agenda, + ;; `org-agenda-multi' is bound non-nil, in which case `org-agenda-finalize' does nothing. + ;; But we do call `org-agenda-finalize-entries', which allows `org-super-agenda' to work. + (->> items + (-map #'org-ql-view--format-element) + org-agenda-finalize-entries + insert) + (insert "\n")))) ;;;###autoload (defalias 'org-ql-block 'org-ql-search-block) diff --git a/org-ql.info b/org-ql.info index 3254983..689d1e2 100644 --- a/org-ql.info +++ b/org-ql.info @@ -723,6 +723,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog for custom Helm commands that search certain files. • Display a message when views are refreshed. (Thanks to xeijin (https://github.com/xeijin).) + • Respect Org Agenda restriction in org-ql-block. (Thanks to Ihor + Radchenko (https://github.com/yantar92) for reporting.) *Fixed* • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 @@ -1028,18 +1030,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03226689 -Node: 03127070 -Node: 0327265 -Node: 02330238 -Node: 02230464 -Node: 02130730 -Node: 0230927 -Node: 0134960 -Node: Notes35059 -Node: Comparison with Org Agenda searches35221 -Node: org-sidebar36092 -Node: License36371 +Node: 03226822 +Node: 03127203 +Node: 0327398 +Node: 02330371 +Node: 02230597 +Node: 02130863 +Node: 0231060 +Node: 0135093 +Node: Notes35192 +Node: Comparison with Org Agenda searches35354 +Node: org-sidebar36225 +Node: License36504  End Tag Table From b7a33170a104f71cf36088c7cabd10e145f78673 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 19 Jan 2020 00:02:03 -0600 Subject: [PATCH 072/560] Fix: (org-ql-view--buffer) Set buffer-read-only Fixes #72. Thanks to @xeijin. --- README.org | 1 + org-ql-view.el | 3 ++- org-ql.info | 27 +++++++++++++++------------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index aa482e0..31c820c 100644 --- a/README.org +++ b/README.org @@ -405,6 +405,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Call =helm-make-source= directly instead of using =helm-build-sync-source= macro. (Fixes [[https://github.com/alphapapa/org-ql/issues/60][#60]]. Thanks to [[https://github.com/matthuszagh][Matt Huszagh]] for reporting.) + Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. + Face for done to-do keywords in =org-ql-view= buffers. (Thanks to [[https://github.com/dsdshcym][Yiming Chen]].) ++ Make view buffers read-only. (Fixes [[https://github.com/alphapapa/org-ql/issues/72][#72]]. Thanks to [[https://github.com/xeijin][xeijin]].) *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql-view.el b/org-ql-view.el index 42cf1fe..c0a8207 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -439,7 +439,8 @@ If NAME is non-nil, return buffer by that name instead of using default buffer." (with-current-buffer (get-buffer-create (or name (concat org-ql-view-buffer-name-prefix "*"))) (unless (eq major-mode 'org-agenda-mode) - (org-agenda-mode)) + (org-agenda-mode) + (setf buffer-read-only t)) (current-buffer))) (defun org-ql-view--format-relative-date (difference) diff --git a/org-ql.info b/org-ql.info index 689d1e2..fe8dacc 100644 --- a/org-ql.info +++ b/org-ql.info @@ -738,6 +738,9 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog side-scrolling of the window when calling end-of-buffer. • Face for done to-do keywords in org-ql-view buffers. (Thanks to Yiming Chen (https://github.com/dsdshcym).) + • Make view buffers read-only. (Fixes #72 + (https://github.com/alphapapa/org-ql/issues/72). Thanks to xeijin + (https://github.com/xeijin).) *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -1030,18 +1033,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03226822 -Node: 03127203 -Node: 0327398 -Node: 02330371 -Node: 02230597 -Node: 02130863 -Node: 0231060 -Node: 0135093 -Node: Notes35192 -Node: Comparison with Org Agenda searches35354 -Node: org-sidebar36225 -Node: License36504 +Node: 03226977 +Node: 03127358 +Node: 0327553 +Node: 02330526 +Node: 02230752 +Node: 02131018 +Node: 0231215 +Node: 0135248 +Node: Notes35347 +Node: Comparison with Org Agenda searches35509 +Node: org-sidebar36380 +Node: License36659  End Tag Table From 610b1179c67cc3e7d113492117f52e3ef19bae0a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:01:03 -0600 Subject: [PATCH 073/560] Add: (org-ql-view-sidebar-sort-views) --- README.org | 1 + org-ql-view.el | 8 +++++++- org-ql.info | 25 +++++++++++++------------ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 31c820c..958ec15 100644 --- a/README.org +++ b/README.org @@ -399,6 +399,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Function ~helm-org-ql-source~, which returns a Helm source that searches given buffers/files with ~helm-org-ql~. It can be used for custom Helm commands that search certain files. + Display a message when views are refreshed. (Thanks to [[https://github.com/xeijin][xeijin]].) + Respect Org Agenda restriction in =org-ql-block=. (Thanks to [[https://github.com/yantar92][Ihor Radchenko]] for reporting.) ++ Option =org-ql-view-sidebar-sort-views=. *Fixed* + Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) diff --git a/org-ql-view.el b/org-ql-view.el index c0a8207..54cde9b 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -115,6 +115,10 @@ See info node `(elisp)Cyclic Window Ordering'." "Side-window slot for Org QL Views list buffer." :type 'integer) +(defcustom org-ql-view-sidebar-sort-views nil + "Sort `org-ql-views' in `org-ql-view-sidebar'." + :type 'boolean) + (defcustom org-ql-views (list (cons "Recent entries" #'org-ql-view-recent-items) (cons "Review (to-do keyword without timestamp in past 2 weeks)" @@ -338,7 +342,9 @@ update search arguments." (erase-buffer) (->> org-ql-views (-map #'car) - (-sort #'string<) + (-sort (if org-ql-view-sidebar-sort-views + #'string< + #'ignore)) (s-join "\n") insert)) (current-buffer))) diff --git a/org-ql.info b/org-ql.info index fe8dacc..0e6f41f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -725,6 +725,7 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog (https://github.com/xeijin).) • Respect Org Agenda restriction in org-ql-block. (Thanks to Ihor Radchenko (https://github.com/yantar92) for reporting.) + • Option org-ql-view-sidebar-sort-views. *Fixed* • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 @@ -1033,18 +1034,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03226977 -Node: 03127358 -Node: 0327553 -Node: 02330526 -Node: 02230752 -Node: 02131018 -Node: 0231215 -Node: 0135248 -Node: Notes35347 -Node: Comparison with Org Agenda searches35509 -Node: org-sidebar36380 -Node: License36659 +Node: 03227023 +Node: 03127404 +Node: 0327599 +Node: 02330572 +Node: 02230798 +Node: 02131064 +Node: 0231261 +Node: 0135294 +Node: Notes35393 +Node: Comparison with Org Agenda searches35555 +Node: org-sidebar36426 +Node: License36705  End Tag Table From 6beada491263c196410226500f4ebd6fbc2a6b07 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:02:44 -0600 Subject: [PATCH 074/560] Change: (org-ql-views) Mouseover text, view names --- README.org | 4 ++ org-ql-view.el | 127 +++++++++++++++++++++++++++---------------------- org-ql.info | 30 +++++++----- 3 files changed, 93 insertions(+), 68 deletions(-) diff --git a/README.org b/README.org index 958ec15..a201ab7 100644 --- a/README.org +++ b/README.org @@ -400,6 +400,10 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Display a message when views are refreshed. (Thanks to [[https://github.com/xeijin][xeijin]].) + Respect Org Agenda restriction in =org-ql-block=. (Thanks to [[https://github.com/yantar92][Ihor Radchenko]] for reporting.) + Option =org-ql-view-sidebar-sort-views=. ++ Mouseover =help-echo= text for =org-ql-views= default view names. + +*Changed* ++ Rename some default =org-ql-views= views. (Users who have modified =org-ql-views= from the default will not see the new names unless they copy them into their config.) *Fixed* + Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) diff --git a/org-ql-view.el b/org-ql-view.el index 54cde9b..07bbc87 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -120,67 +120,82 @@ See info node `(elisp)Cyclic Window Ordering'." :type 'boolean) (defcustom org-ql-views - (list (cons "Recent entries" #'org-ql-view-recent-items) - (cons "Review (to-do keyword without timestamp in past 2 weeks)" + (list (cons "Overview: Agenda-like" + (list :buffers-files #'org-agenda-files + :query '(and (not (done)) + (or (habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today))) + :sort '(date priority todo) + :super-groups 'org-super-agenda-groups + :title "Agenda-like")) + (cons "Overview: NEXT tasks" + (list :buffers-files #'org-agenda-files + :query '(todo "NEXT") + :sort '(priority date) + :super-groups 'org-super-agenda-groups + :title "Overview: NEXT tasks")) + (cons "Calendar: Today" + (list :buffers-files #'org-agenda-files + :query '(ts-active :on today) + :title "Today" + :super-groups 'org-super-agenda-groups + :sort '(priority))) + (cons "Calendar: This week" + (lambda () + "Show items with an active timestamp during this calendar week." + (interactive) + (let* ((ts (ts-now)) + (beg-of-week (->> ts + (ts-adjust 'day (- (ts-dow (ts-now)))) + (ts-apply :hour 0 :minute 0 :second 0))) + (end-of-week (->> ts + (ts-adjust 'day (- 6 (ts-dow (ts-now)))) + (ts-apply :hour 23 :minute 59 :second 59)))) + (org-ql-search (org-agenda-files) + `(ts-active :from ,beg-of-week + :to ,end-of-week) + :title "This week" + :super-groups 'org-super-agenda-groups + :sort '(priority))))) + (cons "Calendar: Next week" + (lambda () + "Show items with an active timestamp during the next calendar week." + (interactive) + (let* ((ts (ts-adjust 'day 7 (ts-now))) + (beg-of-week (->> ts + (ts-adjust 'day (- (ts-dow (ts-now)))) + (ts-apply :hour 0 :minute 0 :second 0))) + (end-of-week (->> ts + (ts-adjust 'day (- 6 (ts-dow (ts-now)))) + (ts-apply :hour 23 :minute 59 :second 59)))) + (org-ql-search (org-agenda-files) + `(ts-active :from ,beg-of-week + :to ,end-of-week) + :title "Next week" + :super-groups 'org-super-agenda-groups + :sort '(priority))))) + (cons "Review: Recently timestamped" #'org-ql-view-recent-items) + (cons (propertize "Review: Stale tasks" + 'help-echo "Tasks without a timestamp in the past 2 weeks") (list :buffers-files #'org-agenda-files :query '(and (todo) (not (ts :from -14))) - :title "Review" + :title (propertize "Review: Stale tasks" + 'help-echo "Tasks without a timestamp in the past 2 weeks") :sort '(date priority todo) :super-groups '((:auto-parent t)))) - (cons "Stuck Projects" (list :buffers-files #'org-agenda-files - :query '(and (todo) - (children) - (not (children (todo "NEXT")))) - :title "Stuck Projects" - :sort '(priority date) - :super-groups 'org-super-agenda-groups)) - (cons "Agenda-like" (list :buffers-files #'org-agenda-files - :query '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today))) - :sort '(date priority todo) - :super-groups 'org-super-agenda-groups - :title "Agenda-like")) - (cons "Today" (list :buffers-files #'org-agenda-files - :query '(ts-active :on today) - :title "Today" - :super-groups 'org-super-agenda-groups - :sort '(priority))) - (cons "This week" (lambda () - "Show items with an active timestamp during this calendar week." - (interactive) - (let* ((ts (ts-now)) - (beg-of-week (->> ts - (ts-adjust 'day (- (ts-dow (ts-now)))) - (ts-apply :hour 0 :minute 0 :second 0))) - (end-of-week (->> ts - (ts-adjust 'day (- 6 (ts-dow (ts-now)))) - (ts-apply :hour 23 :minute 59 :second 59)))) - (org-ql-search (org-agenda-files) - `(ts-active :from ,beg-of-week - :to ,end-of-week) - :title "This week" - :super-groups 'org-super-agenda-groups - :sort '(priority))))) - (cons "Next week" (lambda () - "Show items with an active timestamp during the next calendar week." - (interactive) - (let* ((ts (ts-adjust 'day 7 (ts-now))) - (beg-of-week (->> ts - (ts-adjust 'day (- (ts-dow (ts-now)))) - (ts-apply :hour 0 :minute 0 :second 0))) - (end-of-week (->> ts - (ts-adjust 'day (- 6 (ts-dow (ts-now)))) - (ts-apply :hour 23 :minute 59 :second 59)))) - (org-ql-search (org-agenda-files) - `(ts-active :from ,beg-of-week - :to ,end-of-week) - :title "Next week" - :super-groups 'org-super-agenda-groups - :sort '(priority)))))) + (cons (propertize "Review: Stuck projects" + 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") + (list :buffers-files #'org-agenda-files + :query '(and (todo) + (children) + (not (children (todo "NEXT")))) + :title (propertize "Review: Stuck projects" + 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") + :sort '(priority date) + :super-groups 'org-super-agenda-groups))) "Alist of `org-ql-view' commands." :type '(alist diff --git a/org-ql.info b/org-ql.info index 0e6f41f..d9923f0 100644 --- a/org-ql.info +++ b/org-ql.info @@ -726,6 +726,12 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog • Respect Org Agenda restriction in org-ql-block. (Thanks to Ihor Radchenko (https://github.com/yantar92) for reporting.) • Option org-ql-view-sidebar-sort-views. + • Mouseover help-echo text for org-ql-views default view names. + + *Changed* + • Rename some default org-ql-views views. (Users who have modified + org-ql-views from the default will not see the new names unless + they copy them into their config.) *Fixed* • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 @@ -1034,18 +1040,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03227023 -Node: 03127404 -Node: 0327599 -Node: 02330572 -Node: 02230798 -Node: 02131064 -Node: 0231261 -Node: 0135294 -Node: Notes35393 -Node: Comparison with Org Agenda searches35555 -Node: org-sidebar36426 -Node: License36705 +Node: 03227288 +Node: 03127669 +Node: 0327864 +Node: 02330837 +Node: 02231063 +Node: 02131329 +Node: 0231526 +Node: 0135559 +Node: Notes35658 +Node: Comparison with Org Agenda searches35820 +Node: org-sidebar36691 +Node: License36970  End Tag Table From 9bd1235e00439dad6390ac0a052b86559271694b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:05:16 -0600 Subject: [PATCH 075/560] Meta: Update makem.sh files --- .github/workflows/test.yml | 10 +-- Makefile | 9 ++- makem.sh | 125 ++++++++++++++++++++++++++++++++----- 3 files changed, 120 insertions(+), 24 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9a9c29c..b3c22ed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,8 +28,8 @@ on: pull_request: push: # Comment out this section to enable testing of all branches. - # branches: - # - master + branches: + - master jobs: build: @@ -51,13 +51,15 @@ jobs: run: | SANDBOX_DIR=$(mktemp -d) || exit 1 echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR - ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --auto-install --install package-lint + ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --install-deps --install-linters # The "all" rule is not used, because it treats compilation warnings # as failures, so linting and testing are run as separate steps. - name: Lint - continue-on-error: true + # NOTE: Uncomment this line to treat lint failures as passing + # so the job doesn't show failure. + # continue-on-error: true run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint - name: Test diff --git a/Makefile b/Makefile index 58c5a06..1ca3da4 100644 --- a/Makefile +++ b/Makefile @@ -11,8 +11,11 @@ # conflict with Make's own arguments through Make to the script. # Using -- doesn't seem to do it. -ifdef auto-install - AUTO_INSTALL = "--auto-install" +ifdef install-deps + INSTALL_DEPS = "--install-deps" +endif +ifdef install-linters + INSTALL_LINTERS = "--install-linters" endif ifdef sandbox @@ -46,4 +49,4 @@ endif # directory by that name exists, which can confuse Make. %: - @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR) $(AUTO_INSTALL) $(@) + @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR) $(INSTALL_DEPS) $(INSTALL_LINTERS) $(@) diff --git a/makem.sh b/makem.sh index 4cdf914..9f3538c 100755 --- a/makem.sh +++ b/makem.sh @@ -48,16 +48,21 @@ function usage { cat </dev/null + then + if [[ $direct_p ]] + then + error "$package not available." + else + verbose 2 "$package not available." + fi + return 1 + fi +} + +function ensure-tests-available { + # If tests of type $1 (like "ERT") are available, return 0. Otherwise, if + # $2 is set, give an error and return 1; otherwise give verbose message. $1 + # should have a corresponding predicate command, like ert-tests-p for ERT. + local test_name=$1 + local test_command="${test_name,,}-tests-p" # Converts name to lowercase. + local direct_p=$2 + + if ! $test_command + then + if [[ $direct_p ]] + then + error "$test_name tests not found." + else + verbose 2 "$test_name tests not found." + fi + return 1 + fi +} + function echo_color { # This allows bold, italic, etc. without needing a function for # each variation. @@ -407,9 +459,9 @@ function log { echo "LOG ($(ts)): $@" >&2 } function log_color { - local color=$1 + local color_name=$1 shift - echo_color $color "LOG ($(ts)): $@" >&2 + echo_color $color_name "LOG ($(ts)): $@" >&2 } function success { if [[ $verbose -ge 2 ]] @@ -421,11 +473,11 @@ function verbose { # $1 is the verbosity level, rest are echoed when appropriate. if [[ $verbose -ge $1 ]] then - [[ $1 -eq 1 ]] && local color=blue - [[ $1 -ge 2 ]] && local color=cyan + [[ $1 -eq 1 ]] && local color_name=blue + [[ $1 -ge 2 ]] && local color_name=cyan shift - log_color $color "$@" >&2 + log_color $color_name "$@" >&2 fi } @@ -436,6 +488,9 @@ function ts { # * Rules # These functions are intended to be called as rules, like a Makefile. +# Some rules test $1 to determine whether the rule is being called +# directly or from a meta-rule; if directly, an error is given if the +# rule can't be run, otherwise it's skipped. function all { verbose 1 "Running all rules..." @@ -466,7 +521,7 @@ function batch { } function interactive { - # Run Emacs interactively. Most useful with --sandbox and --auto-install. + # Run Emacs interactively. Most useful with --sandbox and --install-deps. unset arg_batch run_emacs \ $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") @@ -478,6 +533,7 @@ function lint { lint-checkdoc lint-compile + lint-indent lint-package } @@ -504,7 +560,36 @@ function lint-compile { unset compile_error_on_warn } +function lint-indent { + ensure-package-available indent-lint $1 || return $(echo-unset-p $1) + + verbose 1 "Linting indentation..." + + # FIXME: indent-lint outputs a summary line like: + # Diff finished (has differences). Fri Jan 17 10:30:34 2020 + # which is unnecessary for our use and clutters output. + + # We load project source files as well, because they may contain + # macros with (declare (indent)) rules which must be loaded to set + # indentation. However... + + # FIXME: This doesn't appear to actually work: macros that set + # indentation and are correctly indented in the source files are + # reported as having wrong indentation. Not sure if bug in + # indent-lint or here. + + run_emacs \ + --load indent-lint \ + $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") \ + --funcall indent-lint-batch \ + "${files_project_source[@]}" "${files_project_test[@]}" \ + && success "Linting indentation finished without errors." \ + || error "Linting indentation failed." +} + function lint-package { + ensure-package-available package-lint $1 || return $(echo-unset-p $1) + verbose 1 "Linting package..." run_emacs \ @@ -523,7 +608,7 @@ function tests { } function test-buttercup { - buttercup-tests-p || return 0 + ensure-tests-available Buttercup $1 || return $(echo-unset-p $1) compile || die verbose 1 "Running Buttercup tests..." @@ -540,7 +625,7 @@ function test-buttercup { } function test-ert { - ert-tests-p || return 0 + ensure-tests-available ERT $1 || return $(echo-unset-p $1) compile || die verbose 1 "Running ERT tests..." @@ -555,7 +640,7 @@ function test-ert { # * Defaults -test_files_regexp='^(tests?|t)/' +test_files_regexp='^((tests?|t)/)|-test.el$|^test-' emacs_command=("emacs") errors=0 @@ -630,7 +715,7 @@ files_project_byte_compile=("${files_project_source[@]}" "${files_project_test[@ args=$(getopt -n "$0" \ -o dhi:sS:vf:CO \ - -l auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox,sandbox-dir: \ + -l install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox,sandbox-dir: \ -- "$@") \ || { usage; exit 1; } eval set -- "$args" @@ -638,8 +723,12 @@ eval set -- "$args" while true do case "$1" in - --auto-install) - auto_install=true + --install-deps) + install_deps=true + ;; + --install-linters) + args_sandbox_package_install+=(--eval "(package-install 'indent-lint)" + --eval "(package-install 'package-lint)") ;; -d|--debug) debug=true @@ -726,7 +815,9 @@ do batch=true elif type -t "$rule" 2>/dev/null | grep function &>/dev/null then - $rule + # Pass called-directly as $1 to indicate that the rule is + # being called directly rather than from a meta-rule. + $rule called-directly elif [[ $rule = test ]] then # Allow the "tests" rule to be called as "test". Since "test" From 154d3bc9495ec4d8183616711d03f4b9f82c458a Mon Sep 17 00:00:00 2001 From: Jeff Filipovits Date: Tue, 7 Jan 2020 08:02:50 -0500 Subject: [PATCH 076/560] Fix: (org-ql-select) Sorting with single atom sorter Closes #90. Thanks to Jeff Filipovits (@legalnonsense). --- README.org | 1 + org-ql.el | 2 +- org-ql.info | 26 ++++++++++++++------------ 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index a201ab7..3cf51fa 100644 --- a/README.org +++ b/README.org @@ -411,6 +411,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Search/view buffers now always end with a newline, which prevents side-scrolling of the window when calling =end-of-buffer=. + Face for done to-do keywords in =org-ql-view= buffers. (Thanks to [[https://github.com/dsdshcym][Yiming Chen]].) + Make view buffers read-only. (Fixes [[https://github.com/alphapapa/org-ql/issues/72][#72]]. Thanks to [[https://github.com/xeijin][xeijin]].) ++ Sorting with single sorter specified as an atom. (Thanks to [[https://github.com/legalnonsense][Jeff Filipovits]].) *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql.el b/org-ql.el index 27ede79..7e7c0fb 100644 --- a/org-ql.el +++ b/org-ql.el @@ -242,7 +242,7 @@ returns nil or non-nil." (pcase sort (`nil items) ((or 'date 'deadline 'scheduled 'todo 'priority 'random - (guard (cl-loop for elem in sort + (guard (cl-loop for elem in (-list sort) always (memq elem '(date deadline scheduled todo priority random))))) ;; Default sorting functions (org-ql--sort-by items (-list sort))) diff --git a/org-ql.info b/org-ql.info index d9923f0..5618077 100644 --- a/org-ql.info +++ b/org-ql.info @@ -748,6 +748,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog • Make view buffers read-only. (Fixes #72 (https://github.com/alphapapa/org-ql/issues/72). Thanks to xeijin (https://github.com/xeijin).) + • Sorting with single sorter specified as an atom. (Thanks to Jeff + Filipovits (https://github.com/legalnonsense).) *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -1040,18 +1042,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03227288 -Node: 03127669 -Node: 0327864 -Node: 02330837 -Node: 02231063 -Node: 02131329 -Node: 0231526 -Node: 0135559 -Node: Notes35658 -Node: Comparison with Org Agenda searches35820 -Node: org-sidebar36691 -Node: License36970 +Node: 03227414 +Node: 03127795 +Node: 0327990 +Node: 02330963 +Node: 02231189 +Node: 02131455 +Node: 0231652 +Node: 0135685 +Node: Notes35784 +Node: Comparison with Org Agenda searches35946 +Node: org-sidebar36817 +Node: License37096  End Tag Table From 79d9bd59cf00f63f13e770f00c20baa6824d6271 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:23:00 -0600 Subject: [PATCH 077/560] Docs: Add note about 0.5 changes --- README.org | 2 ++ org-ql.info | 32 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 3cf51fa..1ca0ac1 100644 --- a/README.org +++ b/README.org @@ -384,6 +384,8 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre +/Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= automatically, as they will be pushed to the =master= branch when ready. + *Added* + *Commands* - ~helm-org-ql-views~, which shows one of ~org-ql-views~ selected with Helm. diff --git a/org-ql.info b/org-ql.info index 5618077..7eb5138 100644 --- a/org-ql.info +++ b/org-ql.info @@ -699,7 +699,13 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog 5.1 0.4-pre =========== -*Added* +_Note:_ The next release, 0.5, may include changes which will require +minor updates to written queries (e.g. a few predicates may be +renamed). Users who wish to avoid those changes happening unexpectedly +in their configs should avoid upgrading org-ql automatically, as they +will be pushed to the master branch when ready. + + *Added* • *Commands* • ‘helm-org-ql-views’, which shows one of ‘org-ql-views’ selected with Helm. @@ -1042,18 +1048,18 @@ Node: Agenda-like views18025 Node: Listing / acting-on results19430 Node: Changelog24032 Node: 04-pre24569 -Node: 03227414 -Node: 03127795 -Node: 0327990 -Node: 02330963 -Node: 02231189 -Node: 02131455 -Node: 0231652 -Node: 0135685 -Node: Notes35784 -Node: Comparison with Org Agenda searches35946 -Node: org-sidebar36817 -Node: License37096 +Node: 03227742 +Node: 03128123 +Node: 0328318 +Node: 02331291 +Node: 02231517 +Node: 02131783 +Node: 0231980 +Node: 0136013 +Node: Notes36112 +Node: Comparison with Org Agenda searches36274 +Node: org-sidebar37145 +Node: License37424  End Tag Table From 2e0d38daae76af631d5d5ae438ca13b2e2948aea Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:28:11 -0600 Subject: [PATCH 078/560] Tidy: (org-ql-select) Sorting pcase --- org-ql.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 7e7c0fb..effa411 100644 --- a/org-ql.el +++ b/org-ql.el @@ -241,9 +241,8 @@ returns nil or non-nil." ;; Sort items (pcase sort (`nil items) - ((or 'date 'deadline 'scheduled 'todo 'priority 'random - (guard (cl-loop for elem in (-list sort) - always (memq elem '(date deadline scheduled todo priority random))))) + ((guard (cl-loop for elem in (-list sort) + always (memq elem '(date deadline scheduled todo priority random)))) ;; Default sorting functions (org-ql--sort-by items (-list sort))) ;; Sort by user-given comparator. From b00949d9456a7763f3a999870d31ff6cde991aa1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:37:28 -0600 Subject: [PATCH 079/560] Docs: (priority) Update docstring Fixes #81. Thanks to Ihor Radchenko (@yantar92). --- README.org | 2 +- org-ql.info | 52 +++++++++++++++++++++++++++------------------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/README.org b/README.org index 1ca0ac1..40c16dd 100644 --- a/README.org +++ b/README.org @@ -192,7 +192,7 @@ Arguments are listed next to predicate names, where applicable. + =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches ~STRINGS~. Matches ~STRINGS~ as a contiguous segment of the outline path. Each string is compared as a substring. For example the path ~Food/Fruits/Grapes~ would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~. - Aliases: ~olps~. + =path (&rest regexps)= :: Return non-nil if current heading's buffer's filename path matches any of ~REGEXPS~ (regexp strings). Without arguments, return non-nil if buffer is file-backed. -+ =priority (&optional comparator-or-priority priority)= :: Return non-nil if current heading has a certain priority. ~COMPARATOR-OR-PRIORITY~ should be either a comparator function, like ~<=~, or a priority string, like "A" (in which case (~=~ will be the comparator). If ~COMPARATOR-OR-PRIORITY~ is a comparator, ~PRIORITY~ should be a priority string. If both arguments are nil, return non-nil if heading has any defined priority. ++ =priority (&rest args)= :: Return non-nil if current heading has a certain priority. ~ARGS~ may be either a list of one or more priority letters as strings, or a comparator function symbol followed by a priority letter string. For example: ~(priority "A") (priority "A" "B") (priority '>= "B")~ Note that items without a priority cookie never match this predicate (while Org itself considers items without a cookie to have the default priority, which, by default, is equal to priority ~B~). + =property (property &optional value)= :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). Note that property inheritance is currently /not/ enabled for this predicate. If you need to test with inheritance, you could use a custom predicate form, like ~(org-entry-get (point) "PROPERTY" 'inherit)~. + =regexp (&rest regexps)= :: Return non-nil if current entry matches all of ~REGEXPS~ (regexp strings). Matches against entire entry, from beginning of its heading to the next heading. - Aliases: =r=. diff --git a/org-ql.info b/org-ql.info index 7eb5138..9336d3b 100644 --- a/org-ql.info +++ b/org-ql.info @@ -395,13 +395,15 @@ Arguments are listed next to predicate names, where applicable. Return non-nil if current heading’s buffer’s filename path matches any of ‘REGEXPS’ (regexp strings). Without arguments, return non-nil if buffer is file-backed. -‘priority (&optional comparator-or-priority priority)’ - Return non-nil if current heading has a certain priority. - ‘COMPARATOR-OR-PRIORITY’ should be either a comparator function, - like ‘<=’, or a priority string, like "A" (in which case (‘=’ will - be the comparator). If ‘COMPARATOR-OR-PRIORITY’ is a comparator, - ‘PRIORITY’ should be a priority string. If both arguments are nil, - return non-nil if heading has any defined priority. +‘priority (&rest args)’ + Return non-nil if current heading has a certain priority. ‘ARGS’ + may be either a list of one or more priority letters as strings, or + a comparator function symbol followed by a priority letter string. + For example: ‘(priority "A") (priority "A" "B") (priority '>= "B")’ + Note that items without a priority cookie never match this + predicate (while Org itself considers items without a cookie to + have the default priority, which, by default, is equal to priority + ‘B’). ‘property (property &optional value)’ Return non-nil if current entry has ‘PROPERTY’ (a string), and optionally ‘VALUE’ (a string). Note that property inheritance is @@ -1042,24 +1044,24 @@ Node: org-ql-sparse-tree6635 Node: Queries7435 Node: Non-sexp query syntax8296 Node: Predicates9995 -Node: Date/time predicates15157 -Node: Functions / Macros17792 -Node: Agenda-like views18025 -Node: Listing / acting-on results19430 -Node: Changelog24032 -Node: 04-pre24569 -Node: 03227742 -Node: 03128123 -Node: 0328318 -Node: 02331291 -Node: 02231517 -Node: 02131783 -Node: 0231980 -Node: 0136013 -Node: Notes36112 -Node: Comparison with Org Agenda searches36274 -Node: org-sidebar37145 -Node: License37424 +Node: Date/time predicates15217 +Node: Functions / Macros17852 +Node: Agenda-like views18085 +Node: Listing / acting-on results19490 +Node: Changelog24092 +Node: 04-pre24629 +Node: 03227802 +Node: 03128183 +Node: 0328378 +Node: 02331351 +Node: 02231577 +Node: 02131843 +Node: 0232040 +Node: 0136073 +Node: Notes36172 +Node: Comparison with Org Agenda searches36334 +Node: org-sidebar37205 +Node: License37484  End Tag Table From dc26e938fa2e25628b3c3c1ddff8f2f97fb7f695 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 17:45:33 -0600 Subject: [PATCH 080/560] Fix: (org-ql-block) Autoloads Fixes #53. Thanks to reports from Gus Cantieni (@gcantieni), Karl Voit (@novoid), rieje (@rieje), and Jake | Junxuan (@jakejx). --- README.org | 1 + org-ql-search.el | 1 + org-ql.info | 29 +++++++++++++++++------------ 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/README.org b/README.org index 40c16dd..4a1ecbd 100644 --- a/README.org +++ b/README.org @@ -414,6 +414,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Face for done to-do keywords in =org-ql-view= buffers. (Thanks to [[https://github.com/dsdshcym][Yiming Chen]].) + Make view buffers read-only. (Fixes [[https://github.com/alphapapa/org-ql/issues/72][#72]]. Thanks to [[https://github.com/xeijin][xeijin]].) + Sorting with single sorter specified as an atom. (Thanks to [[https://github.com/legalnonsense][Jeff Filipovits]].) ++ Autoload for =org-ql-block= agenda block. (Fixes [[https://github.com/alphapapa/org-ql/issues/53][#53]]. Thanks to reports from [[https://github.com/gcantieni][Gus Cantieni]], [[https://github.com/novoid][Karl Voit]], [[https://github.com/rieje][rieje]], and [[https://github.com/jakejx][Jake | Junxuan]].) *Internal* + Added generic node data cache to speed up recursive, tree-based queries. diff --git a/org-ql-search.el b/org-ql-search.el index fab0e95..d97d59e 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -219,6 +219,7 @@ necessary." (org-ql-view--display :buffer buffer :header header :string (s-join "\n" strings))))) +;;;###autoload (defun org-ql-search-block (query) "Insert items for QUERY into current buffer. QUERY should be an `org-ql' query form. Intended to be used as a diff --git a/org-ql.info b/org-ql.info index 9336d3b..6419125 100644 --- a/org-ql.info +++ b/org-ql.info @@ -758,6 +758,11 @@ will be pushed to the master branch when ready. (https://github.com/xeijin).) • Sorting with single sorter specified as an atom. (Thanks to Jeff Filipovits (https://github.com/legalnonsense).) + • Autoload for org-ql-block agenda block. (Fixes #53 + (https://github.com/alphapapa/org-ql/issues/53). Thanks to reports + from Gus Cantieni (https://github.com/gcantieni), Karl Voit + (https://github.com/novoid), rieje (https://github.com/rieje), and + Jake | Junxuan (https://github.com/jakejx).) *Internal* • Added generic node data cache to speed up recursive, tree-based @@ -1050,18 +1055,18 @@ Node: Agenda-like views18085 Node: Listing / acting-on results19490 Node: Changelog24092 Node: 04-pre24629 -Node: 03227802 -Node: 03128183 -Node: 0328378 -Node: 02331351 -Node: 02231577 -Node: 02131843 -Node: 0232040 -Node: 0136073 -Node: Notes36172 -Node: Comparison with Org Agenda searches36334 -Node: org-sidebar37205 -Node: License37484 +Node: 03228121 +Node: 03128502 +Node: 0328697 +Node: 02331670 +Node: 02231896 +Node: 02132162 +Node: 0232359 +Node: 0136392 +Node: Notes36491 +Node: Comparison with Org Agenda searches36653 +Node: org-sidebar37524 +Node: License37803  End Tag Table From 090debabc7aa5b15c825cb4ab061f451ec40939c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 21:14:08 -0600 Subject: [PATCH 081/560] Meta: Fix test.yml It's easy to overwrite these local changes, but easy to revert them as well. --- .github/workflows/test.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3c22ed..6930896 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,8 +28,8 @@ on: pull_request: push: # Comment out this section to enable testing of all branches. - branches: - - master + # branches: + # - master jobs: build: @@ -57,9 +57,7 @@ jobs: # as failures, so linting and testing are run as separate steps. - name: Lint - # NOTE: Uncomment this line to treat lint failures as passing - # so the job doesn't show failure. - # continue-on-error: true + continue-on-error: true run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint - name: Test From b8a4a539836a6f73bfe13bf5769ed679e19c2ac4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:24:54 -0600 Subject: [PATCH 082/560] Change: (org-ql-views/Stuck projects) Use descendants, not children --- README.org | 4 +++- org-ql-view.el | 4 ++-- org-ql.info | 33 ++++++++++++++++++--------------- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/README.org b/README.org index 4a1ecbd..4922e12 100644 --- a/README.org +++ b/README.org @@ -405,7 +405,9 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Mouseover =help-echo= text for =org-ql-views= default view names. *Changed* -+ Rename some default =org-ql-views= views. (Users who have modified =org-ql-views= from the default will not see the new names unless they copy them into their config.) ++ Some default =org-ql-view= views (users who have modified =org-ql-views= from the default will not see the new views unless they copy them into their config): + - Rename some views. + - "Stuck projects" view (now uses =descendants= instead of =children=, which is more useful. *Fixed* + Inherit file tags when =org-tag-inheritance= is enabled. (Fixes [[https://github.com/alphapapa/org-ql/issues/55][#55]]. Thanks to [[https://github.com/mskorzhinskiy][Mikhail Skorzhinskiy]].) diff --git a/org-ql-view.el b/org-ql-view.el index 07bbc87..4ce6a37 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -190,8 +190,8 @@ See info node `(elisp)Cyclic Window Ordering'." 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") (list :buffers-files #'org-agenda-files :query '(and (todo) - (children) - (not (children (todo "NEXT")))) + (descendants (todo)) + (not (descendants (todo "NEXT")))) :title (propertize "Review: Stuck projects" 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") :sort '(priority date) diff --git a/org-ql.info b/org-ql.info index 6419125..5184668 100644 --- a/org-ql.info +++ b/org-ql.info @@ -737,9 +737,12 @@ will be pushed to the master branch when ready. • Mouseover help-echo text for org-ql-views default view names. *Changed* - • Rename some default org-ql-views views. (Users who have modified - org-ql-views from the default will not see the new names unless - they copy them into their config.) + • Some default org-ql-view views (users who have modified + org-ql-views from the default will not see the new views unless + they copy them into their config): + • Rename some views. + • "Stuck projects" view (now uses descendants instead of + children, which is more useful. *Fixed* • Inherit file tags when org-tag-inheritance is enabled. (Fixes #55 @@ -1055,18 +1058,18 @@ Node: Agenda-like views18085 Node: Listing / acting-on results19490 Node: Changelog24092 Node: 04-pre24629 -Node: 03228121 -Node: 03128502 -Node: 0328697 -Node: 02331670 -Node: 02231896 -Node: 02132162 -Node: 0232359 -Node: 0136392 -Node: Notes36491 -Node: Comparison with Org Agenda searches36653 -Node: org-sidebar37524 -Node: License37803 +Node: 03228251 +Node: 03128632 +Node: 0328827 +Node: 02331800 +Node: 02232026 +Node: 02132292 +Node: 0232489 +Node: 0136522 +Node: Notes36621 +Node: Comparison with Org Agenda searches36783 +Node: org-sidebar37654 +Node: License37933  End Tag Table From 65fb37c30d6c0764a5f9f2b17b7062439804740e Mon Sep 17 00:00:00 2001 From: Josh Moller-Mara Date: Wed, 18 Dec 2019 01:01:47 +0800 Subject: [PATCH 083/560] Add: parent and ancestors predicates These predicates are analogs to the existing "children" and "descendents" predicates. They may be useful for testing parents for specific todo states, or if they have non-inherited tags (i.e. tags from "org-tags-exclude-from-inheritance"). --- README.org | 3 +++ org-ql.el | 73 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 47 insertions(+), 29 deletions(-) diff --git a/README.org b/README.org index 4922e12..23f672f 100644 --- a/README.org +++ b/README.org @@ -181,7 +181,9 @@ Arguments are listed next to predicate names, where applicable. + =category (&optional categories)= :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + =children (&optional query)= :: Return non-nil if current heading has direct child headings. If ~QUERY~, test it against child headings. This selector may be nested, e.g. to match grandchild headings. ++ =parent (&optional query)= :: Return non-nil if current heading has a direct parent heading. If ~QUERY~, test it against the parent heading. This selector may be nested, e.g. to match grandparent headings. + =descendants (&optional query)= :: Return non-nil if current heading has descendant headings. If ~QUERY~, test it against descendant headings. This selector may be nested (if you can grok the nesting!). ++ =ancestors (&optional query)= :: Return non-nil if current heading has ancestor headings (which is true if it has a parent heading). With ~QUERY~, return non-nil if some ancestor heading matches it. This selector may also be nested. + =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + =habit= :: Return non-nil if entry is a habit. + =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). @@ -395,6 +397,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience - Negation of terms in plain queries using ~!~. For example, ~tags:space !moon~ to exclude entries which contain ~moon~. - Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). - Predicate ~src~, which matches Org Babel source blocks. + - Predicates =parent= and =ancestors=. - Alias =h= for =heading= predicate. - Alias =r= for =regexp= predicate. (Thanks to [[https://github.com/tumashu][Feng Shu]].) + Info manual. diff --git a/org-ql.el b/org-ql.el index effa411..e643ca5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -548,6 +548,10 @@ Replaces bare strings with (regexp) selectors, and appropriate (`(children) '(children (lambda () t))) (`(descendants ,query) `(descendants ',query)) (`(descendants) '(descendants (lambda () t))) + (`(parent ,query) `(parent ,(org-ql--query-predicate (rec query)))) + (`(parent) `(parent ,(org-ql--query-predicate (rec '(lambda () t))))) + (`(ancestors ,query) `(ancestors ,(org-ql--query-predicate (rec query)))) + (`(ancestors) `(ancestors ,(org-ql--query-predicate (rec '(lambda () t))))) ;; Timestamp-based predicates. I think this is the way that makes the most sense: ;; set the limit to N days in the future, adjusted to 23:59:59 (since Org doesn't ;; support timestamps down to the second, anyway, there should be no need to adjust @@ -931,38 +935,49 @@ Arguments STRING, POS, FILL, and LEVEL are according to (org-ql--defpred children (query) "Return non-nil if current entry has children matching QUERY." - (save-excursion - (save-restriction - (org-narrow-to-subtree) - (when (org-goto-first-child) - ;; Lisp makes this easy and elegant: all we do is modify the query, - ;; nesting it inside an (and), and it doesn't descend into grandchildren. - (let* ((level (org-current-level)) - (query (cl-typecase query - (byte-code-function `(and (level ,level) - (funcall ,query))) - (t `(and (level ,level) - ,query))))) - (catch 'found - (org-ql-select (current-buffer) - query - :narrow t - :action (lambda () - (throw 'found t))))))))) + (org-with-wide-buffer + ;; Widening is needed if inside an "ancestors" query + (org-narrow-to-subtree) + (when (org-goto-first-child) + ;; Lisp makes this easy and elegant: all we do is modify the query, + ;; nesting it inside an (and), and it doesn't descend into grandchildren. + (let* ((level (org-current-level)) + (query (cl-typecase query + (byte-code-function `(and (level ,level) + (funcall ,query))) + (t `(and (level ,level) + ,query))))) + (catch 'found + (org-ql-select (current-buffer) + query + :narrow t + :action (lambda () + (throw 'found t)))))))) + +(org-ql--defpred parent (predicate) + "Return non-nil if the current entry's parent satisfies PREDICATE." + (org-with-wide-buffer + (when (org-up-heading-safe) + (org-ql--value-at (point) predicate)))) (org-ql--defpred descendants (query) "Return non-nil if current entry has descendants matching QUERY." - (save-excursion - (save-restriction - (org-narrow-to-subtree) - (when (org-goto-first-child) - (narrow-to-region (point) (point-max)) - (catch 'found - (org-ql-select (current-buffer) - query - :narrow t - :action (lambda () - (throw 'found t)))))))) + (org-with-wide-buffer + (org-narrow-to-subtree) + (when (org-goto-first-child) + (narrow-to-region (point) (point-max)) + (catch 'found + (org-ql-select (current-buffer) + query + :narrow t + :action (lambda () + (throw 'found t))))))) + +(org-ql--defpred ancestors (predicate) + "Return non-nil if any of current entry's ancestors satisfy PREDICATE." + (org-with-wide-buffer + (cl-loop while (org-up-heading-safe) + thereis (org-ql--value-at (point) predicate)))) (org-ql--defpred category (&rest categories) "Return non-nil if current heading is in one or more of CATEGORIES (a list of strings)." From e48cdf71437cb5030b23048486bb848afd569d9a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 13 Jan 2020 20:22:53 -0600 Subject: [PATCH 084/560] Tests: Add ancestor/parent tests --- tests/test-org-ql.el | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 2d1e6ed..982e226 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -347,6 +347,24 @@ RESULTS should be a list of strings as returned by ;; TODO: Other predicates. + (describe "(ancestors)" + (org-ql-it "without sub-query" + (org-ql-expect ((ancestors)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + + (org-ql-it "with sub-query" + (org-ql-expect ((ancestors (heading "universe"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + + (describe "(parent)" + (org-ql-it "without sub-query" + (org-ql-expect ((parent)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + + (org-ql-it "with sub-query" + (org-ql-expect ((parent (and (todo) (priority "A")))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (describe "(category)" (org-ql-it "without arguments" From 3003eb8ad490a89861ddce3ffb21df5f7bec0af4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 18:42:20 -0600 Subject: [PATCH 085/560] Comment: Add tasks --- org-ql.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org-ql.el b/org-ql.el index e643ca5..ec41546 100644 --- a/org-ql.el +++ b/org-ql.el @@ -941,6 +941,9 @@ Arguments STRING, POS, FILL, and LEVEL are according to (when (org-goto-first-child) ;; Lisp makes this easy and elegant: all we do is modify the query, ;; nesting it inside an (and), and it doesn't descend into grandchildren. + + ;; TODO: However, this could probably be rewritten like the `ancestors' predicate, + ;; which avoids calling `org-ql-select' recursively and its associated overhead. (let* ((level (org-current-level)) (query (cl-typecase query (byte-code-function `(and (level ,level) @@ -962,6 +965,8 @@ Arguments STRING, POS, FILL, and LEVEL are according to (org-ql--defpred descendants (query) "Return non-nil if current entry has descendants matching QUERY." + ;; TODO: This could probably be rewritten like the `ancestors' predicate, + ;; which avoids calling `org-ql-select' recursively and its associated overhead. (org-with-wide-buffer (org-narrow-to-subtree) (when (org-goto-first-child) From adc5447c7287082dec8cb16ec90ac634147b75bf Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 22:45:16 -0600 Subject: [PATCH 086/560] Tidy/Comment: Ancestor/descendant predicates --- org-ql.el | 119 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/org-ql.el b/org-ql.el index ec41546..90f752f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -933,57 +933,6 @@ Arguments STRING, POS, FILL, and LEVEL are according to ;;;;; Predicates -(org-ql--defpred children (query) - "Return non-nil if current entry has children matching QUERY." - (org-with-wide-buffer - ;; Widening is needed if inside an "ancestors" query - (org-narrow-to-subtree) - (when (org-goto-first-child) - ;; Lisp makes this easy and elegant: all we do is modify the query, - ;; nesting it inside an (and), and it doesn't descend into grandchildren. - - ;; TODO: However, this could probably be rewritten like the `ancestors' predicate, - ;; which avoids calling `org-ql-select' recursively and its associated overhead. - (let* ((level (org-current-level)) - (query (cl-typecase query - (byte-code-function `(and (level ,level) - (funcall ,query))) - (t `(and (level ,level) - ,query))))) - (catch 'found - (org-ql-select (current-buffer) - query - :narrow t - :action (lambda () - (throw 'found t)))))))) - -(org-ql--defpred parent (predicate) - "Return non-nil if the current entry's parent satisfies PREDICATE." - (org-with-wide-buffer - (when (org-up-heading-safe) - (org-ql--value-at (point) predicate)))) - -(org-ql--defpred descendants (query) - "Return non-nil if current entry has descendants matching QUERY." - ;; TODO: This could probably be rewritten like the `ancestors' predicate, - ;; which avoids calling `org-ql-select' recursively and its associated overhead. - (org-with-wide-buffer - (org-narrow-to-subtree) - (when (org-goto-first-child) - (narrow-to-region (point) (point-max)) - (catch 'found - (org-ql-select (current-buffer) - query - :narrow t - :action (lambda () - (throw 'found t))))))) - -(org-ql--defpred ancestors (predicate) - "Return non-nil if any of current entry's ancestors satisfy PREDICATE." - (org-with-wide-buffer - (cl-loop while (org-up-heading-safe) - thereis (org-ql--value-at (point) predicate)))) - (org-ql--defpred category (&rest categories) "Return non-nil if current heading is in one or more of CATEGORIES (a list of strings)." (when-let ((category (org-get-category (point)))) @@ -1213,6 +1162,74 @@ language." ;; No regexps to check: return non-nil. t)))))) +;;;;;; Ancestor/descendant + +;; These predicates search ancestor and descendant headings for sub-queries. + +;; Note that the implementations of the upward-searching, ancestor/parent predicates differ +;; from that of the downward-searching, descendants/children predicates in that the former +;; take a predicate function as their argument and test it on each heading (the predicate +;; being created by the `--query-pre-process' function, which see), while the latter take an +;; `org-ql' query form as their argument and execute another `org-ql-select' query inside of +;; the currently running query. This "split" implementation seems like the most generally +;; efficient one, because searching descendants searches potentially many more headings than +;; searching ancestors, so executing a full query in that case can be faster due to use of +;; the "preambles" provided by running a full query. However, see note below. + +(org-ql--defpred parent (predicate) + "Return non-nil if the current entry's parent satisfies PREDICATE." + (org-with-wide-buffer + (when (org-up-heading-safe) + (org-ql--value-at (point) predicate)))) + +(org-ql--defpred ancestors (predicate) + "Return non-nil if any of current entry's ancestors satisfy PREDICATE." + (org-with-wide-buffer + (cl-loop while (org-up-heading-safe) + thereis (org-ql--value-at (point) predicate)))) + +;; MAYBE: The `children' and `descendants' predicates could probably be rewritten like +;; the `ancestors' predicate, which avoids calling `org-ql-select' recursively and its +;; associated overhead. However, that would preclude the use of preambles, so depending +;; on the Org file being searched and the sub-query, performance could be better or +;; worse. It should be benchmarked extensively before so changing the implementation. + +(org-ql--defpred children (query) + "Return non-nil if current entry has children matching QUERY." + (org-with-wide-buffer + ;; Widening is needed if inside an "ancestors" query + (org-narrow-to-subtree) + (when (org-goto-first-child) + ;; Lisp makes this easy and elegant: all we do is modify the query, + ;; nesting it inside an (and), and it doesn't descend into grandchildren. + (let* ((level (org-current-level)) + (query (cl-typecase query + (byte-code-function `(and (level ,level) + (funcall ,query))) + (t `(and (level ,level) + ,query))))) + (catch 'found + (org-ql-select (current-buffer) + query + :narrow t + :action (lambda () + (throw 'found t)))))))) + +(org-ql--defpred descendants (query) + "Return non-nil if current entry has descendants matching QUERY." + ;; TODO: This could probably be rewritten like the `ancestors' predicate, + ;; which avoids calling `org-ql-select' recursively and its associated overhead. + (org-with-wide-buffer + (org-narrow-to-subtree) + (when (org-goto-first-child) + (narrow-to-region (point) (point-max)) + (catch 'found + (org-ql-select (current-buffer) + query + :narrow t + :action (lambda () + (throw 'found t))))))) + ;;;;;; Timestamps ;; TODO: Remove the _on vars from these arg lists. I think they're not From 0e1196fd6f6bb35d9027578590e3986461beb3a9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 22:53:57 -0600 Subject: [PATCH 087/560] Tidy/Docs/Comment: Ancestor/descendant predicates --- README.org | 23 +++++++++++++++-------- org-ql.el | 16 ++++++++++------ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/README.org b/README.org index 23f672f..dd58a61 100644 --- a/README.org +++ b/README.org @@ -143,10 +143,14 @@ Show a sparse tree for ~QUERY~ in ~BUFFER~ and return number of results. The tr ~QUERY~ is an ~org-ql~ query sexp (quoted, since this is a function). ~BUFFER~ defaults to the current buffer. When ~KEEP-PREVIOUS~ is non-nil (interactively, with prefix), the outline is not reset to the overview state before finding matches, which allows stacking calls to this command. Runs ~org-occur-hook~ after making the sparse tree. ** Queries +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: :CONTENTS: -- [[#non-sexp-query-syntax][Non-sexp query syntax]] -- [[#predicates][Predicates]] -- [[#datetime-predicates][Date/time predicates]] +- [[#non-sexp-query-syntax][Non-sexp query syntax]] +- [[#general-predicates][General predicates]] +- [[#ancestordescendant-predicates][Ancestor/descendant predicates]] +- [[#datetime-predicates][Date/time predicates]] :END: An =org-ql= query is a lisp form which may contain arbitrary lisp forms, as well as certain built-in predicates. It is byte-compiled into a predicate function which is tested with point on each heading in an Org buffer; when it returns non-nil, the heading matches the query. @@ -175,15 +179,11 @@ The command =org-ql-search= also accepts, and the command =helm-org-ql= only acc Note that the =priority= predicate does not support comparators in the non-sexp syntax, so multiple priorities should be passed instead, as seen in the last example. -*** Predicates +*** General predicates Arguments are listed next to predicate names, where applicable. + =category (&optional categories)= :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). -+ =children (&optional query)= :: Return non-nil if current heading has direct child headings. If ~QUERY~, test it against child headings. This selector may be nested, e.g. to match grandchild headings. -+ =parent (&optional query)= :: Return non-nil if current heading has a direct parent heading. If ~QUERY~, test it against the parent heading. This selector may be nested, e.g. to match grandparent headings. -+ =descendants (&optional query)= :: Return non-nil if current heading has descendant headings. If ~QUERY~, test it against descendant headings. This selector may be nested (if you can grok the nesting!). -+ =ancestors (&optional query)= :: Return non-nil if current heading has ancestor headings (which is true if it has a parent heading). With ~QUERY~, return non-nil if some ancestor heading matches it. This selector may also be nested. + =done= :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + =habit= :: Return non-nil if entry is a habit. + =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). @@ -208,6 +208,13 @@ Arguments are listed next to predicate names, where applicable. - Aliases: ~tags&~. + =todo (&optional keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). +*** Ancestor/descendant predicates + ++ =ancestors (&optional query)= :: Return non-nil if current heading has ancestor headings. If ~QUERY~, return non-nil if an ancestor heading matches it. This selector may be nested. ++ =children (&optional query)= :: Return non-nil if current heading has direct child headings. If ~QUERY~, return non-nil if a child heading matches it. This selector may be nested, e.g. to match grandchild headings. ++ =descendants (&optional query)= :: Return non-nil if current heading has descendant headings. If ~QUERY~, return non-nil if a descendant heading matches it. This selector may be nested (if you can grok the nesting!). ++ =parent (&optional query)= :: Return non-nil if current heading has a direct parent heading. If ~QUERY~, return non-nil if the parent heading matches it. This selector may be nested, e.g. to match grandparent headings. + *** Date/time predicates All of these predicates take optional keyword arguments ~:from~, ~:to:~, and ~:on~: diff --git a/org-ql.el b/org-ql.el index 90f752f..279d747 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1169,18 +1169,16 @@ language." ;; Note that the implementations of the upward-searching, ancestor/parent predicates differ ;; from that of the downward-searching, descendants/children predicates in that the former ;; take a predicate function as their argument and test it on each heading (the predicate -;; being created by the `--query-pre-process' function, which see), while the latter take an +;; being created by the `--pre-process-query' function, which see), while the latter take an ;; `org-ql' query form as their argument and execute another `org-ql-select' query inside of ;; the currently running query. This "split" implementation seems like the most generally ;; efficient one, because searching descendants searches potentially many more headings than ;; searching ancestors, so executing a full query in that case can be faster due to use of ;; the "preambles" provided by running a full query. However, see note below. -(org-ql--defpred parent (predicate) - "Return non-nil if the current entry's parent satisfies PREDICATE." - (org-with-wide-buffer - (when (org-up-heading-safe) - (org-ql--value-at (point) predicate)))) +;; NOTE: The ancestors and parent predicates' docstrings are developer-facing +;; rather than user-facing, since their arguments are predicates provided +;; automatically by `--pre-process-query'. (org-ql--defpred ancestors (predicate) "Return non-nil if any of current entry's ancestors satisfy PREDICATE." @@ -1188,6 +1186,12 @@ language." (cl-loop while (org-up-heading-safe) thereis (org-ql--value-at (point) predicate)))) +(org-ql--defpred parent (predicate) + "Return non-nil if the current entry's parent satisfies PREDICATE." + (org-with-wide-buffer + (when (org-up-heading-safe) + (org-ql--value-at (point) predicate)))) + ;; MAYBE: The `children' and `descendants' predicates could probably be rewritten like ;; the `ancestors' predicate, which avoids calling `org-ql-select' recursively and its ;; associated overhead. However, that would preclude the use of preambles, so depending From 18c6787244604064ed7c0bbd795c013401225e54 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 22:56:04 -0600 Subject: [PATCH 088/560] Tidy: (org-ql--pre-process-query) Calling of --query-predicate --- org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 279d747..70e7ea5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -549,9 +549,9 @@ Replaces bare strings with (regexp) selectors, and appropriate (`(descendants ,query) `(descendants ',query)) (`(descendants) '(descendants (lambda () t))) (`(parent ,query) `(parent ,(org-ql--query-predicate (rec query)))) - (`(parent) `(parent ,(org-ql--query-predicate (rec '(lambda () t))))) + (`(parent) '(parent (lambda () t))) (`(ancestors ,query) `(ancestors ,(org-ql--query-predicate (rec query)))) - (`(ancestors) `(ancestors ,(org-ql--query-predicate (rec '(lambda () t))))) + (`(ancestors) '(ancestors (lambda () t))) ;; Timestamp-based predicates. I think this is the way that makes the most sense: ;; set the limit to N days in the future, adjusted to 23:59:59 (since Org doesn't ;; support timestamps down to the second, anyway, there should be no need to adjust From 22cacbd8fe46e549400c3164533cc4648f60dea8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 22:59:13 -0600 Subject: [PATCH 089/560] Docs: Add credit --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index dd58a61..46ff63a 100644 --- a/README.org +++ b/README.org @@ -404,7 +404,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience - Negation of terms in plain queries using ~!~. For example, ~tags:space !moon~ to exclude entries which contain ~moon~. - Predicates =outline-path= (alias =olp=) and =outline-path-segment= (alias =olps=). - Predicate ~src~, which matches Org Babel source blocks. - - Predicates =parent= and =ancestors=. + - Predicates =parent= and =ancestors=. (Thanks to [[https://github.com/mm--][Josh Moller-Mara]].) - Alias =h= for =heading= predicate. - Alias =r= for =regexp= predicate. (Thanks to [[https://github.com/tumashu][Feng Shu]].) + Info manual. From 8f2baa10a3573b1f487dbc176dc68adcd88d370d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:02:10 -0600 Subject: [PATCH 090/560] Docs: Fix ToC, info file --- README.org | 13 ++++-- org-ql.info | 123 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 82 insertions(+), 54 deletions(-) diff --git a/README.org b/README.org index 46ff63a..0103630 100644 --- a/README.org +++ b/README.org @@ -60,10 +60,17 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: #+END_SRC * Usage +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: :CONTENTS: -- [[#commands][Commands]] -- [[#queries][Queries]] -- [[#functions--macros][Functions / Macros]] +- [[#commands][Commands]] +- [[#queries][Queries]] + - [[#non-sexp-query-syntax][Non-sexp query syntax]] + - [[#general-predicates][General predicates]] + - [[#ancestordescendant-predicates][Ancestor/descendant predicates]] + - [[#datetime-predicates][Date/time predicates]] +- [[#functions--macros][Functions / Macros]] :END: # These links work on GitHub's Org renderer but not in Org. diff --git a/org-ql.info b/org-ql.info index 5184668..08b38c5 100644 --- a/org-ql.info +++ b/org-ql.info @@ -50,7 +50,8 @@ Commands Queries * Non-sexp query syntax:: -* Predicates:: +* General predicates:: +* Ancestor/descendant predicates:: * Date/time predicates:: @@ -146,7 +147,8 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top 4 Usage ******* - • • • + • • + • • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -294,7 +296,7 @@ File: README.info, Node: Queries, Next: Functions / Macros, Prev: Commands, 4.2 Queries =========== - • • • + • • • • An org-ql query is a lisp form which may contain arbitrary lisp forms, as well as certain built-in predicates. It is byte-compiled into a predicate function which is tested with point on each heading in an @@ -311,11 +313,12 @@ Org buffer; when it returns non-nil, the heading matches the query. * Menu: * Non-sexp query syntax:: -* Predicates:: +* General predicates:: +* Ancestor/descendant predicates:: * Date/time predicates::  -File: README.info, Node: Non-sexp query syntax, Next: Predicates, Up: Queries +File: README.info, Node: Non-sexp query syntax, Next: General predicates, Up: Queries 4.2.1 Non-sexp query syntax --------------------------- @@ -345,24 +348,16 @@ non-sexp syntax, so multiple priorities should be passed instead, as seen in the last example.  -File: README.info, Node: Predicates, Next: Date/time predicates, Prev: Non-sexp query syntax, Up: Queries +File: README.info, Node: General predicates, Next: Ancestor/descendant predicates, Prev: Non-sexp query syntax, Up: Queries -4.2.2 Predicates ----------------- +4.2.2 General predicates +------------------------ Arguments are listed next to predicate names, where applicable. ‘category (&optional categories)’ Return non-nil if current heading is in one or more of ‘CATEGORIES’ (a list of strings). -‘children (&optional query)’ - Return non-nil if current heading has direct child headings. If - ‘QUERY’, test it against child headings. This selector may be - nested, e.g. to match grandchild headings. -‘descendants (&optional query)’ - Return non-nil if current heading has descendant headings. If - ‘QUERY’, test it against descendant headings. This selector may be - nested (if you can grok the nesting!). ‘done’ Return non-nil if entry’s ‘TODO’ keyword is in ‘org-done-keywords’. ‘habit’ @@ -444,9 +439,32 @@ Arguments are listed next to predicate names, where applicable. ‘org-done-keywords’).  -File: README.info, Node: Date/time predicates, Prev: Predicates, Up: Queries +File: README.info, Node: Ancestor/descendant predicates, Next: Date/time predicates, Prev: General predicates, Up: Queries -4.2.3 Date/time predicates +4.2.3 Ancestor/descendant predicates +------------------------------------ + +‘ancestors (&optional query)’ + Return non-nil if current heading has ancestor headings. If + ‘QUERY’, return non-nil if an ancestor heading matches it. This + selector may be nested. +‘children (&optional query)’ + Return non-nil if current heading has direct child headings. If + ‘QUERY’, return non-nil if a child heading matches it. This + selector may be nested, e.g. to match grandchild headings. +‘descendants (&optional query)’ + Return non-nil if current heading has descendant headings. If + ‘QUERY’, return non-nil if a descendant heading matches it. This + selector may be nested (if you can grok the nesting!). +‘parent (&optional query)’ + Return non-nil if current heading has a direct parent heading. If + ‘QUERY’, return non-nil if the parent heading matches it. This + selector may be nested, e.g. to match grandparent headings. + + +File: README.info, Node: Date/time predicates, Prev: Ancestor/descendant predicates, Up: Queries + +4.2.4 Date/time predicates -------------------------- All of these predicates take optional keyword arguments ‘:from’, ‘:to:’, @@ -722,6 +740,8 @@ will be pushed to the master branch when ready. • Predicates outline-path (alias olp) and outline-path-segment (alias olps). • Predicate ‘src’, which matches Org Babel source blocks. + • Predicates parent and ancestors. (Thanks to Josh Moller-Mara + (https://github.com/mm--).) • Alias h for heading predicate. • Alias r for regexp predicate. (Thanks to Feng Shu (https://github.com/tumashu).) @@ -1037,39 +1057,40 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1367 -Node: Screenshots1541 -Node: Installation1659 -Node: Quelpa2297 -Node: Usage2740 -Node: Commands3064 -Node: org-ql-search3537 -Node: helm-org-ql5185 -Node: org-ql-view5597 -Node: org-ql-view-sidebar5795 -Node: org-ql-view-recent-items6151 -Node: org-ql-sparse-tree6635 -Node: Queries7435 -Node: Non-sexp query syntax8296 -Node: Predicates9995 -Node: Date/time predicates15217 -Node: Functions / Macros17852 -Node: Agenda-like views18085 -Node: Listing / acting-on results19490 -Node: Changelog24092 -Node: 04-pre24629 -Node: 03228251 -Node: 03128632 -Node: 0328827 -Node: 02331800 -Node: 02232026 -Node: 02132292 -Node: 0232489 -Node: 0136522 -Node: Notes36621 -Node: Comparison with Org Agenda searches36783 -Node: org-sidebar37654 -Node: License37933 +Node: Contents1410 +Node: Screenshots1584 +Node: Installation1702 +Node: Quelpa2340 +Node: Usage2783 +Node: Commands3132 +Node: org-ql-search3605 +Node: helm-org-ql5253 +Node: org-ql-view5665 +Node: org-ql-view-sidebar5863 +Node: org-ql-view-recent-items6219 +Node: org-ql-sparse-tree6703 +Node: Queries7503 +Node: Non-sexp query syntax8411 +Node: General predicates10118 +Node: Ancestor/descendant predicates14925 +Node: Date/time predicates16053 +Node: Functions / Macros18708 +Node: Agenda-like views18941 +Node: Listing / acting-on results20346 +Node: Changelog24948 +Node: 04-pre25485 +Node: 03229219 +Node: 03129600 +Node: 0329795 +Node: 02332768 +Node: 02232994 +Node: 02133260 +Node: 0233457 +Node: 0137490 +Node: Notes37589 +Node: Comparison with Org Agenda searches37751 +Node: org-sidebar38622 +Node: License38901  End Tag Table From 66f58b97f266b8e149418f72e6cd5513aff26fcd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:12:11 -0600 Subject: [PATCH 091/560] Docs: Add examples, update ToC --- examples.org | 83 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 11 deletions(-) diff --git a/examples.org b/examples.org index af84e17..4167330 100644 --- a/examples.org +++ b/examples.org @@ -2,17 +2,20 @@ * Contents :PROPERTIES: -:TOC: this +:TOC: :include siblings :ignore this +:END: +:CONTENTS: +- [[#agenda-like-view][Agenda-like view]] +- [[#entries-from-the-past-week][Entries from the past week]] +- [[#find-entries-matching-a-certain-custom_id][Find entries matching a certain CUSTOM_ID]] +- [[#listing-bills-coming-due][Listing bills coming due]] +- [[#music-database][Music database]] +- [[#return-org-elements][Return Org elements]] +- [[#set-tags-on-certain-entries][Set tags on certain entries]] +- [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]] +- [[#stuck-projects-block-agenda][Stuck projects block agenda]] +- [[#subproject-and-subtask-queries][Subproject and subtask queries]] :END: - - [[#agenda-like-view][Agenda-like view]] - - [[#entries-from-the-past-week][Entries from the past week]] - - [[#find-entries-matching-a-certain-custom_id][Find entries matching a certain CUSTOM_ID]] - - [[#listing-bills-coming-due][Listing bills coming due]] - - [[#music-database][Music database]] - - [[#return-org-elements][Return Org elements]] - - [[#set-tags-on-certain-entries][Set tags on certain entries]] - - [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]] - - [[#stuck-projects-block-agenda][Stuck projects block agenda]] * Agenda-like view @@ -173,9 +176,67 @@ With this =org-ql-block= agenda view, like: ((org-ql-block-header "Stuck Projects"))))))) #+END_SRC +* Subproject and subtask queries + +#+BEGIN_SRC elisp + ;; Search for subprojects. + (org-ql-search (org-agenda-files) + '(and (todo "PROJECT") + (ancestors (todo "PROJECT")))) + + ;; Search for all subtasks of projects, grouped by parent heading. + (org-ql-search (org-agenda-files) + '(and (todo) + (ancestors (todo "PROJECT"))) + :super-groups '((:auto-parent t))) + + ;; Search for direct top-level tasks of projects. + (org-ql-search (org-agenda-files) + '(and (todo) + (parent (todo "PROJECT"))) + :super-groups '((:auto-parent t))) +#+END_SRC + +Of course, all of those presume using a =PROJECT= keyword to define projects. If one defines a project as any task which has an ancestor task, one could use queries like: + +#+BEGIN_SRC elisp + ;; Search for all subtasks of top-level projects, grouped by parent heading. + (org-ql-search (org-agenda-files) + '(and (todo) + (ancestors + (and (todo) + (not (parent))))) + :super-groups '((:auto-parent t))) + + ;; Search for all subtasks of all projects, including subprojects, grouped by project. + (org-ql-search (org-agenda-files) + '(and (todo) + (ancestors (todo))) + :super-groups '((:auto-parent t))) +#+END_SRC + +Other interesting queries: + +#+BEGIN_SRC elisp + ;; Subtasks of upcoming deadline items. + (org-ql-search (org-agenda-files) + '(and (todo) + (ancestors + (and (not (done)) + (deadline auto)))) + :super-groups '((:auto-parent t))) + + ;; TODO items whose ancestor is already DONE, and should therefore be + ;; either marked DONE or CANCELLED. + (org-ql-search (org-agenda-files) + '(and (todo) + (ancestors (done))) + :super-groups '((:auto-parent t))) +#+END_SRC + * COMMENT Code :noexport: :PROPERTIES: -:TOC: ignore +:TOC: :ignore (this descendants) :END: ** File-local variables From 843564ad8c6f381e190d93ff9502b94f068bee95 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:15:00 -0600 Subject: [PATCH 092/560] Add: (org-ql-views) Dangling tasks view --- README.org | 1 + org-ql-view.el | 9 +++++++++ org-ql.info | 27 +++++++++++++++------------ 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/README.org b/README.org index 0103630..dadb623 100644 --- a/README.org +++ b/README.org @@ -420,6 +420,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + Respect Org Agenda restriction in =org-ql-block=. (Thanks to [[https://github.com/yantar92][Ihor Radchenko]] for reporting.) + Option =org-ql-view-sidebar-sort-views=. + Mouseover =help-echo= text for =org-ql-views= default view names. ++ "Dangling tasks" default view in =org-ql-views=. (Users who have modified =org-ql-views= from the default will not see the new view unless they copy it into their config.) *Changed* + Some default =org-ql-view= views (users who have modified =org-ql-views= from the default will not see the new views unless they copy them into their config): diff --git a/org-ql-view.el b/org-ql-view.el index 4ce6a37..f141270 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -177,6 +177,15 @@ See info node `(elisp)Cyclic Window Ordering'." :super-groups 'org-super-agenda-groups :sort '(priority))))) (cons "Review: Recently timestamped" #'org-ql-view-recent-items) + (cons (propertize "Review: Dangling tasks" + 'help-echo "Tasks whose ancestor is done") + (list :buffers-files #'org-agenda-files + :query '(and (todo) + (ancestors (done))) + :title (propertize "Review: Dangling tasks" + 'help-echo "Tasks whose ancestor is done") + :sort '(date priority todo) + :super-groups '((:auto-parent t)))) (cons (propertize "Review: Stale tasks" 'help-echo "Tasks without a timestamp in the past 2 weeks") (list :buffers-files #'org-agenda-files diff --git a/org-ql.info b/org-ql.info index 08b38c5..78c67b3 100644 --- a/org-ql.info +++ b/org-ql.info @@ -755,6 +755,9 @@ will be pushed to the master branch when ready. Radchenko (https://github.com/yantar92) for reporting.) • Option org-ql-view-sidebar-sort-views. • Mouseover help-echo text for org-ql-views default view names. + • "Dangling tasks" default view in org-ql-views. (Users who have + modified org-ql-views from the default will not see the new view + unless they copy it into their config.) *Changed* • Some default org-ql-view views (users who have modified @@ -1079,18 +1082,18 @@ Node: Agenda-like views18941 Node: Listing / acting-on results20346 Node: Changelog24948 Node: 04-pre25485 -Node: 03229219 -Node: 03129600 -Node: 0329795 -Node: 02332768 -Node: 02232994 -Node: 02133260 -Node: 0233457 -Node: 0137490 -Node: Notes37589 -Node: Comparison with Org Agenda searches37751 -Node: org-sidebar38622 -Node: License38901 +Node: 03229405 +Node: 03129786 +Node: 0329981 +Node: 02332954 +Node: 02233180 +Node: 02133446 +Node: 0233643 +Node: 0137676 +Node: Notes37775 +Node: Comparison with Org Agenda searches37937 +Node: org-sidebar38808 +Node: License39087  End Tag Table From 6e55723e270fea28fd403ce98e1c309d2a55a5a1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:38:34 -0600 Subject: [PATCH 093/560] Docs: Clarify change notice --- README.org | 2 +- org-ql.info | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.org b/README.org index dadb623..35c1c3b 100644 --- a/README.org +++ b/README.org @@ -400,7 +400,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.4-pre -/Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= automatically, as they will be pushed to the =master= branch when ready. +/Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= beyond 0.4 automatically, as they will be pushed to the =master= branch when ready. *Added* + *Commands* diff --git a/org-ql.info b/org-ql.info index 78c67b3..59aabc9 100644 --- a/org-ql.info +++ b/org-ql.info @@ -722,8 +722,8 @@ File: README.info, Node: 04-pre, Next: 032, Up: Changelog _Note:_ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly -in their configs should avoid upgrading org-ql automatically, as they -will be pushed to the master branch when ready. +in their configs should avoid upgrading org-ql beyond 0.4 automatically, +as they will be pushed to the master branch when ready. *Added* • *Commands* @@ -1082,18 +1082,18 @@ Node: Agenda-like views18941 Node: Listing / acting-on results20346 Node: Changelog24948 Node: 04-pre25485 -Node: 03229405 -Node: 03129786 -Node: 0329981 -Node: 02332954 -Node: 02233180 -Node: 02133446 -Node: 0233643 -Node: 0137676 -Node: Notes37775 -Node: Comparison with Org Agenda searches37937 -Node: org-sidebar38808 -Node: License39087 +Node: 03229416 +Node: 03129797 +Node: 0329992 +Node: 02332965 +Node: 02233191 +Node: 02133457 +Node: 0233654 +Node: 0137687 +Node: Notes37786 +Node: Comparison with Org Agenda searches37948 +Node: org-sidebar38819 +Node: License39098  End Tag Table From 538373bb481cf82f3b373184da65cf051d6064e8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Jan 2020 23:39:25 -0600 Subject: [PATCH 094/560] Release: 0.4 --- README.org | 2 +- org-ql.el | 2 +- org-ql.info | 80 ++++++++++++++++++++++++++--------------------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/README.org b/README.org index 35c1c3b..eabd92a 100644 --- a/README.org +++ b/README.org @@ -398,7 +398,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. -** 0.4-pre +** 0.4 /Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= beyond 0.4 automatically, as they will be pushed to the =master= branch when ready. diff --git a/org-ql.el b/org-ql.el index 70e7ea5..2eec565 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4-pre +;; Version: 0.4 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index 59aabc9..1915891 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,7 +63,7 @@ Functions / Macros Changelog -* 0.4-pre: 04-pre. +* 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. * 0.3: 03. @@ -703,7 +703,7 @@ releases. * Menu: -* 0.4-pre: 04-pre. +* 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. * 0.3: 03. @@ -714,10 +714,10 @@ releases. * 0.1: 01.  -File: README.info, Node: 04-pre, Next: 032, Up: Changelog +File: README.info, Node: 04, Next: 032, Up: Changelog -5.1 0.4-pre -=========== +5.1 0.4 +======= _Note:_ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be @@ -795,7 +795,7 @@ as they will be pushed to the master branch when ready. queries.  -File: README.info, Node: 032, Next: 031, Prev: 04-pre, Up: Changelog +File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog 5.2 0.3.2 ========= @@ -1060,40 +1060,40 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1410 -Node: Screenshots1584 -Node: Installation1702 -Node: Quelpa2340 -Node: Usage2783 -Node: Commands3132 -Node: org-ql-search3605 -Node: helm-org-ql5253 -Node: org-ql-view5665 -Node: org-ql-view-sidebar5863 -Node: org-ql-view-recent-items6219 -Node: org-ql-sparse-tree6703 -Node: Queries7503 -Node: Non-sexp query syntax8411 -Node: General predicates10118 -Node: Ancestor/descendant predicates14925 -Node: Date/time predicates16053 -Node: Functions / Macros18708 -Node: Agenda-like views18941 -Node: Listing / acting-on results20346 -Node: Changelog24948 -Node: 04-pre25485 -Node: 03229416 -Node: 03129797 -Node: 0329992 -Node: 02332965 -Node: 02233191 -Node: 02133457 -Node: 0233654 -Node: 0137687 -Node: Notes37786 -Node: Comparison with Org Agenda searches37948 -Node: org-sidebar38819 -Node: License39098 +Node: Contents1402 +Node: Screenshots1576 +Node: Installation1694 +Node: Quelpa2332 +Node: Usage2775 +Node: Commands3124 +Node: org-ql-search3597 +Node: helm-org-ql5245 +Node: org-ql-view5657 +Node: org-ql-view-sidebar5855 +Node: org-ql-view-recent-items6211 +Node: org-ql-sparse-tree6695 +Node: Queries7495 +Node: Non-sexp query syntax8403 +Node: General predicates10110 +Node: Ancestor/descendant predicates14917 +Node: Date/time predicates16045 +Node: Functions / Macros18700 +Node: Agenda-like views18933 +Node: Listing / acting-on results20338 +Node: Changelog24940 +Node: 0425469 +Node: 03229388 +Node: 03129765 +Node: 0329960 +Node: 02332933 +Node: 02233159 +Node: 02133425 +Node: 0233622 +Node: 0137655 +Node: Notes37754 +Node: Comparison with Org Agenda searches37916 +Node: org-sidebar38787 +Node: License39066  End Tag Table From 035c20fc28e33ee48f51ec023b7cbd41c84ad177 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 4 Feb 2020 02:47:53 -0600 Subject: [PATCH 095/560] Docs: Update comparison --- README.org | 8 +------- org-ql.info | 11 ++++------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/README.org b/README.org index eabd92a..47032a4 100644 --- a/README.org +++ b/README.org @@ -566,13 +566,7 @@ Of course, queries like these can already be written with Org Agenda searches, b +lisp +{^\*+\s-+TO-READ\s-} #+END_EXAMPLE -But with ~org-ql-agenda~, you would write: - -#+BEGIN_SRC elisp - (org-ql-agenda - (and (regexp "lisp") - (todo "TO-READ"))) -#+END_SRC +But with =org-ql-search=, you would write a query like =lisp todo:TO-READ=, or in Lisp syntax, ~(and "lisp" (todo "TO-READ"))~. ** org-sidebar diff --git a/org-ql.info b/org-ql.info index 1915891..b0e6fad 100644 --- a/org-ql.info +++ b/org-ql.info @@ -1032,11 +1032,8 @@ regular expression syntax, like this: +lisp +{^\*+\s-+TO-READ\s-} - But with ‘org-ql-agenda’, you would write: - - (org-ql-agenda - (and (regexp "lisp") - (todo "TO-READ"))) + But with org-ql-search, you would write a query like +lisp todo:TO-READ, or in Lisp syntax, ‘(and "lisp" (todo "TO-READ"))’.  File: README.info, Node: org-sidebar, Prev: Comparison with Org Agenda searches, Up: Notes @@ -1092,8 +1089,8 @@ Node: 0233622 Node: 0137655 Node: Notes37754 Node: Comparison with Org Agenda searches37916 -Node: org-sidebar38787 -Node: License39066 +Node: org-sidebar38788 +Node: License39067  End Tag Table From e23a026fe5cc2f7563743949bf08f98d72e017b9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Feb 2020 12:42:07 -0600 Subject: [PATCH 096/560] Meta: Update makem.sh, Makefile, and pre-push Use local .sandbox sandbox. (Assumes it is initialized.) --- Makefile | 16 ++- hooks/pre-push | 2 +- makem.sh | 380 ++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 320 insertions(+), 78 deletions(-) diff --git a/Makefile b/Makefile index 1ca3da4..ce9cdd8 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,11 @@ ifdef install-linters endif ifdef sandbox - SANDBOX = "--sandbox" -endif - -ifdef sandbox-dir - SANDBOX_DIR = "--sandbox-dir" "$(sandbox-dir)" + ifeq ($(sandbox), t) + SANDBOX = --sandbox + else + SANDBOX = --sandbox $(sandbox) + endif endif ifdef debug @@ -49,4 +49,8 @@ endif # directory by that name exists, which can confuse Make. %: - @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR) $(INSTALL_DEPS) $(INSTALL_LINTERS) $(@) + @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(INSTALL_DEPS) $(INSTALL_LINTERS) $(@) + +.DEFAULT: init +init: + @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(INSTALL_DEPS) $(INSTALL_LINTERS) diff --git a/hooks/pre-push b/hooks/pre-push index 34976fa..45ef92a 100755 --- a/hooks/pre-push +++ b/hooks/pre-push @@ -14,4 +14,4 @@ read local_ref local_sha remote_ref remote_sha # cause remote code to be downloaded and executed (i.e. what would # happen by installing packages). It can be done manually when needed. -make test +make sandbox=.sandbox test diff --git a/makem.sh b/makem.sh index 9f3538c..cab8458 100755 --- a/makem.sh +++ b/makem.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # * makem.sh --- Script to aid building and testing Emacs Lisp packages @@ -59,17 +59,20 @@ Rules: lint Run all linters, ignoring unavailable ones. lint-checkdoc Run checkdoc. lint-compile Byte-compile source files with warnings as errors. - lint-indent Run indent-lint. + lint-declare Run check-declare. + lint-indent Lint indentation. lint-package Run package-lint. + lint-regexps Run relint. - test, tests Run all tests, ignoring missing test types. - test-buttercup Run Buttercup tests. - test-ert Run ERT tests. + test, tests Run all tests, ignoring missing test types. + test-buttercup Run Buttercup tests. + test-ert Run ERT tests. + test-ert-interactive Run ERT tests interactively. batch Run Emacs in batch mode, loading project source and test files automatically, with remaining args (after "--") passed to Emacs. interactive Run Emacs interactively, loading project source and test files - automatically. + automatically, with remaining args (after "--") passed to Emacs. Options: -d, --debug Print debug info. @@ -78,23 +81,33 @@ Options: --debug-load-path Print load-path from inside Emacs. - -f FILE, --file FILE Check FILE in addition to discovered files. + -E, --emacs PATH Run Emacs at PATH. + + -e, --exclude FILE Exclude FILE from linting and testing. + -f, --file FILE Check FILE in addition to discovered files. --no-color Disable color output. -C, --no-compile Don't compile files automatically. Sandbox options: - -s, --sandbox Run Emacs with an empty config in a temporary - directory (removing directory on exit). - -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it - on exit). Implies -s. + -s, --sandbox [DIR] Run Emacs with an empty config in a sandbox DIR. + If DIR does not exist, make it. If DIR is not + specified, use a temporary sandbox directory and + delete it afterward, implying --install-deps and + --install-linters. --install-deps Automatically install package dependencies. --install-linters Automatically install linters. -i, --install PACKAGE Install PACKAGE before running rules. + An Emacs version-specific subdirectory is automatically made inside + the sandbox, allowing testing with multiple Emacs versions. When + specifying a sandbox directory, use options --install-deps and + --install-linters on first-run and omit them afterward to save time. + Source files are automatically discovered from git, or may be specified with options. Package dependencies are discovered from -"Package-Requires" headers in source files and from a Cask file. +"Package-Requires" headers in source files, from -pkg.el files, and +from a Cask file. EOF } @@ -142,11 +155,69 @@ function elisp-checkdoc-file { (when makem-checkdoc-errors-p (kill-emacs 1)))) +(setq checkdoc-spellcheck-documentation-flag t) (makem-checkdoc-files-and-exit) EOF echo $file } +function elisp-check-declare-file { + # Since check-declare doesn't have a batch function that exits + # non-zero when errors are found, we make one. + local file=$(mktemp) + + cat >$file <"$file" </dev/null | egrep "\.el$" | filter-files-exclude +function dirs-project { + # Echo list of directories to be used in load path. + files-project-feature | dirnames + files-project-test | dirnames } -function files-project-source { - # Echo list of Elisp files that are not tests. - files-project-elisp | egrep -v "$test_files_regexp" | filter-files-feature +function files-project-elisp { + # Echo list of Elisp files in project. + git ls-files 2>/dev/null \ + | egrep "\.el$" \ + | filter-files-exclude-default \ + | filter-files-exclude-args +} + +function files-project-feature { + # Echo list of Elisp files that are not tests and provide a feature. + files-project-elisp \ + | egrep -v "$test_files_regexp" \ + | filter-files-feature } function files-project-test { @@ -232,16 +315,42 @@ function files-project-test { files-project-elisp | egrep "$test_files_regexp" } -function filter-files-exclude { +function dirnames { + # Echo directory names for files on STDIN. + while read file + do + dirname "$file" + done +} + +function filter-files-exclude-default { # Filter out paths (STDIN) which should be excluded by default. egrep -v "(/\.cask/|-autoloads.el|.dir-locals)" } +function filter-files-exclude-args { + # Filter out paths (STDIN) which are excluded with --exclude. + if [[ ${files_exclude[@]} ]] + then + ( + # We use a subshell to set IFS temporarily so we can send + # the list of files to grep -F. This is ugly but more + # correct than replacing spaces with line breaks. Note + # that, for some reason, using IFS="\n" or IFS='\n' doesn't + # work, and a literal line break seems to be required. + IFS=" +" + grep -Fv "${files_exclude[*]}" + ) + else + cat + fi +} + function filter-files-feature { # Read paths on STDIN and echo ones that (provide 'a-feature). while read path do - debug "PATH: $path" egrep "^\\(provide '" "$path" &>/dev/null \ && echo "$path" done @@ -255,6 +364,14 @@ function args-load-files { done } +function args-load-path { + # Echo load-path arguments. + for path in $(dirs-project | sort -u) + do + printf -- '-L %q ' "$path" + done +} + function test-files-p { # Return 0 if $files_project_test is non-empty. [[ "${files_project_test[@]}" ]] @@ -283,7 +400,7 @@ function dependencies { # Echo list of package dependencies. # Search package headers. - egrep '^;; Package-Requires: ' $(files-project-source) $(files-project-test) \ + egrep '^;; Package-Requires: ' $(files-project-feature) $(files-project-test) \ | egrep -o '\([^([:space:]][^)]*\)' \ | egrep -o '^[^[:space:])]+' \ | sed -r 's/\(//g' \ @@ -295,6 +412,12 @@ function dependencies { egrep '\(depends-on "[^"]+"' Cask \ | sed -r -e 's/\(depends-on "([^"]+)".*/\1/g' fi + + # Search -pkg.el file. + if [[ $(git ls-files ./*-pkg.el 2>/dev/null) ]] + then + sed -nr 's/.*\(([-[:alnum:]]+)[[:blank:]]+"[.[:digit:]]+"\).*/\1/p' $(git ls-files ./*-pkg.el 2>/dev/null) + fi } # ** Sandbox @@ -308,7 +431,18 @@ function sandbox { if [[ $sandbox_dir ]] then # Directory given as argument: ensure it exists. - [[ -d $sandbox_dir ]] || die "Directory doesn't exist: $sandbox_dir" + if ! [[ -d $sandbox_dir ]] + then + debug "Making sandbox directory: $sandbox_dir" + mkdir -p "$sandbox_dir" || die "Unable to make sandbox dir." + fi + + # Add Emacs version-specific subdirectory, creating if necessary. + sandbox_dir="$sandbox_dir/$(emacs-version)" + if ! [[ -d $sandbox_dir ]] + then + mkdir "$sandbox_dir" || die "Unable to make sandbox subdir: $sandbox_dir" + fi else # Not given: make temp directory, and delete it on exit. local sandbox_dir=$(mktemp -d) || die "Unable to make sandbox dir." @@ -322,6 +456,7 @@ function sandbox { # Set sandbox args. This is a global variable used by the run_emacs function. args_sandbox=( + --title "makem.sh: $(basename $(pwd)) (sandbox: $sandbox_dir)" --eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))" --eval "(setq user-init-file (file-truename \"$init_file\"))" "${args_load_init_file[@]}" @@ -339,6 +474,15 @@ function sandbox { done fi + # Add package-install arguments for linters. + if [[ $install_linters ]] + then + debug "Installing linters: package-lint relint" + + args_sandbox_package_install+=(--eval "(package-install 'package-lint)" + --eval "(package-install 'relint)") + fi + # *** Install packages into sandbox if [[ ${args_sandbox_package_install[@]} ]] @@ -485,6 +629,21 @@ function ts { date "+%Y-%m-%d %H:%M:%S" } +function emacs-version { + # Echo Emacs version number. + + # Don't use run_emacs function, which does more than we need. + "${emacs_command[@]}" -Q --batch --eval "(princ emacs-version)" \ + || die "Unable to get Emacs version." +} + +function rule-p { + # Return 0 if $1 is a rule. + [[ $1 =~ ^(lint-?|tests?)$ ]] \ + || [[ $1 =~ ^(batch|interactive)$ ]] \ + || [[ $(type -t "$2" 2>/dev/null) =~ function ]] +} + # * Rules # These functions are intended to be called as rules, like a Makefile. @@ -516,15 +675,16 @@ function batch { verbose 1 "Executing Emacs with arguments: ${args_batch[@]}" run_emacs \ - $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") \ - "${args_batch[@]}" + $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ + "${args_batch_interactive[@]}" } function interactive { # Run Emacs interactively. Most useful with --sandbox and --install-deps. unset arg_batch run_emacs \ - $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") + $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ + "${args_batch_interactive[@]}" arg_batch="--batch" } @@ -533,8 +693,10 @@ function lint { lint-checkdoc lint-compile + lint-declare lint-indent lint-package + lint-regexps } function lint-checkdoc { @@ -545,7 +707,7 @@ function lint-checkdoc { run_emacs \ --load="$checkdoc_file" \ - "${files_project_source[@]}" \ + "${files_project_feature[@]}" \ && success "Linting checkdoc finished without errors." \ || error "Linting checkdoc failed." } @@ -560,29 +722,32 @@ function lint-compile { unset compile_error_on_warn } +function lint-declare { + verbose 1 "Linting declarations..." + + local check_declare_file="$(elisp-check-declare-file)" + paths_temp+=("$check_declare_file") + + run_emacs \ + --load "$check_declare_file" \ + -f makem-check-declare-files-and-exit \ + "${files_project_feature[@]}" \ + && success "Linting declarations finished without errors." \ + || error "Linting declarations failed." +} + function lint-indent { - ensure-package-available indent-lint $1 || return $(echo-unset-p $1) - verbose 1 "Linting indentation..." - # FIXME: indent-lint outputs a summary line like: - # Diff finished (has differences). Fri Jan 17 10:30:34 2020 - # which is unnecessary for our use and clutters output. - # We load project source files as well, because they may contain # macros with (declare (indent)) rules which must be loaded to set - # indentation. However... - - # FIXME: This doesn't appear to actually work: macros that set - # indentation and are correctly indented in the source files are - # reported as having wrong indentation. Not sure if bug in - # indent-lint or here. + # indentation. run_emacs \ - --load indent-lint \ - $(args-load-files "${files_project_source[@]}" "${files_project_test[@]}") \ - --funcall indent-lint-batch \ - "${files_project_source[@]}" "${files_project_test[@]}" \ + --load "$(elisp-lint-indent-file)" \ + $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ + --funcall makem-lint-indent-batch-and-exit \ + "${files_project_feature[@]}" "${files_project_test[@]}" \ && success "Linting indentation finished without errors." \ || error "Linting indentation failed." } @@ -595,11 +760,24 @@ function lint-package { run_emacs \ --load package-lint \ --funcall package-lint-batch-and-exit \ - "${files_project_source[@]}" \ + "${files_project_feature[@]}" \ && success "Linting package finished without errors." \ || error "Linting package failed." } +function lint-regexps { + ensure-package-available relint $1 || return $(echo-unset-p $1) + + verbose 1 "Linting regexps..." + + run_emacs \ + --load relint \ + --funcall relint-batch \ + "${files_project_source[@]}" \ + && success "Linting regexps finished without errors." \ + || error "Linting regexps failed." +} + function tests { verbose 1 "Running all tests..." @@ -607,6 +785,16 @@ function tests { test-buttercup } +function test-ert-interactive { + verbose 1 "Running ERT tests interactively..." + + unset arg_batch + run_emacs \ + $(args-load-files "${files_project_test[@]}") \ + --eval "(ert-run-tests-interactively t)" + arg_batch="--batch" +} + function test-buttercup { ensure-tests-available Buttercup $1 || return $(echo-unset-p $1) compile || die @@ -617,9 +805,8 @@ function test-buttercup { paths_temp+=("$buttercup_file") run_emacs \ - --load buttercup \ - --load "$buttercup_file" \ - -f buttercup-run-discover \ + $(args-load-files "${files_project_test[@]}") \ + -f buttercup-run \ && success "Buttercup tests finished without errors." \ || error "Buttercup tests failed." } @@ -672,7 +859,6 @@ color=true # something, which seems like getting too smart for our own good. # TODO: Emit a warning if .ELC files that don't match any .EL files are detected. -load_path="." # ** Colors @@ -703,19 +889,11 @@ args_package_init=( elisp_org_package_archive="(add-to-list 'package-archives '(\"org\" . \"https://orgmode.org/elpa/\") t)" -# * Project files - -# MAYBE: Option to not byte-compile test files. (OTOH, byte-compiling reveals many -# errors that would otherwise go unnoticed, so it's worth it to fix the warnings.) -files_project_source=($(files-project-source)) -files_project_test=($(files-project-test)) -files_project_byte_compile=("${files_project_source[@]}" "${files_project_test[@]}") - # * Args args=$(getopt -n "$0" \ - -o dhi:sS:vf:CO \ - -l install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox,sandbox-dir: \ + -o dhe:E:i:s:vf:CO \ + -l exclude:,emacs:,install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox: \ -- "$@") \ || { usage; exit 1; } eval set -- "$args" @@ -727,12 +905,13 @@ do install_deps=true ;; --install-linters) - args_sandbox_package_install+=(--eval "(package-install 'indent-lint)" - --eval "(package-install 'package-lint)") + install_linters=true ;; -d|--debug) debug=true verbose=2 + args_debug=(--eval "(setq init-file-debug t)" + --eval "(setq debug-on-error t)") ;; --debug-load-path) debug_load_path=true @@ -741,21 +920,52 @@ do usage exit ;; + -E|--emacs) + shift + emacs_command=($1) + ;; -i|--install) shift args_sandbox_package_install+=(--eval "(package-install '$1)") ;; -s|--sandbox) sandbox=true - ;; - -S|--sandbox-dir) - shift - sandbox=true - sandbox_dir="$1" + # Check whether next argument is an option, rule, or a sandbox directory. + if [[ $2 ]] && ! [[ $2 =~ ^-- ]] \ + && ! rule-p "$2" + then + debug "Sandbox dir: $1" + shift + sandbox_dir="$1" + else + debug "No sandbox dir: installing dependencies." + install_deps=true + # HACK: Next argument is another option, so prepend blank arg to the + # argument list so it will be processed by next loop iteration. getopts + # doesn't allow options to have optional arguments, so we do this manually. + if [[ $2 =~ ^- ]] + then + # Next argument is an option: process it next. + new_args=("" "$@") + else + # Next argument is not an option: put it on the end. + new_arg="$2" + shift + shift + new_args=("" "$@" "$new_arg") + fi + debug "Setting new args: ${new_args[@]}" + set -- "${new_args[@]}" + fi ;; -v|--verbose) ((verbose++)) ;; + -e|--exclude) + shift + debug "Excluding file: $1" + files_exclude+=("$1") + ;; -f|--file) shift project_source_files+=("$1") @@ -792,27 +1002,54 @@ paths_temp+=("$package_initialize_file") trap cleanup EXIT INT TERM -if ! [[ ${files_project_source[@]} ]] +# Discover project files. +files_project_feature=($(files-project-feature)) +files_project_test=($(files-project-test)) +files_project_byte_compile=("${files_project_feature[@]}" "${files_project_test[@]}") + +debug "EXCLUDING FILES: ${files_exclude[@]}" +debug "FEATURE FILES: ${files_project_feature[@]}" +debug "TEST FILES: ${files_project_test[@]}" +debug "BYTE-COMPILE FILES: ${files_project_byte_compile[@]}" + +if ! [[ ${files_project_feature[@]} ]] then error "No files specified and not in a git repo." exit 1 fi +# Set load path. +args_load_paths=($(args-load-path)) +debug "LOAD PATH ARGS: ${args_load_paths[@]}" + +# If rules include linters and sandbox-dir is unspecified, install +# linters automatically. +if [[ $sandbox && ! $sandbox_dir ]] && [[ "${rest[@]}" =~ lint ]] +then + debug "Installing linters automatically." + install_linters=true +fi + # Initialize sandbox. [[ $sandbox ]] && sandbox # Run rules. for rule in "${rest[@]}" do - if [[ $batch ]] + if [[ $batch || $interactive ]] then - debug "Adding batch argument: $rule" - args_batch+=("$rule") + debug "Adding batch/interactive argument: $rule" + args_batch_interactive+=("$rule") elif [[ $rule = batch ]] then # Remaining arguments are passed to Emacs. batch=true + elif [[ $rule = interactive ]] + then + # Remaining arguments are passed to Emacs. + interactive=true + elif type -t "$rule" 2>/dev/null | grep function &>/dev/null then # Pass called-directly as $1 to indicate that the rule is @@ -828,8 +1065,9 @@ do fi done -# The batch rule. +# Batch/interactive rules. [[ $batch ]] && batch +[[ $interactive ]] && interactive if [[ $errors -gt 0 ]] then From 8baeeea49e4f94d5e6d2c5c84b0f4b17eae9a450 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Feb 2020 13:56:40 -0600 Subject: [PATCH 097/560] Notes: Add idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 61522a5..d082ce3 100644 --- a/notes.org +++ b/notes.org @@ -598,6 +598,10 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** MAYBE Fancier plain query syntax for tags and properties + +e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. + ** MAYBE Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. From ef0c5220c2cace1743ec82bd8656539b15d55c4e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 28 Jan 2020 00:42:27 -0600 Subject: [PATCH 098/560] Meta: 0.5-pre --- README.org | 4 ++++ org-ql.el | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 47032a4..077ea04 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,10 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.5-pre + +Nothing new yet. + ** 0.4 /Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= beyond 0.4 automatically, as they will be pushed to the =master= branch when ready. diff --git a/org-ql.el b/org-ql.el index 2eec565..c41abd3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4 +;; Version: 0.5-pre ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda From 70f03b200f23f19e0254ba6d9c622b9d5e6b403f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 28 Jan 2020 00:52:02 -0600 Subject: [PATCH 099/560] Docs: Move a screenshot to examples --- README.org | 1 - examples.org | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 077ea04..b199954 100644 --- a/README.org +++ b/README.org @@ -30,7 +30,6 @@ It includes three libraries: The =org-ql= library is flexible and may be used as [[images/org-ql-search.gif]] -[[images/org-ql-search-snippet.png]] [[images/helm-org-ql.gif]] diff --git a/examples.org b/examples.org index 4167330..eb14f08 100644 --- a/examples.org +++ b/examples.org @@ -15,6 +15,7 @@ - [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]] - [[#stuck-projects-block-agenda][Stuck projects block agenda]] - [[#subproject-and-subtask-queries][Subproject and subtask queries]] +- [[#task-list-for-files-in-subdirectories][Task list for files in subdirectories]] :END: * Agenda-like view @@ -234,6 +235,10 @@ Other interesting queries: :super-groups '((:auto-parent t))) #+END_SRC +* Task list for files in subdirectories + +[[images/org-ql-search-snippet.png]] + * COMMENT Code :noexport: :PROPERTIES: :TOC: :ignore (this descendants) From 68a1cf29b64f059569493b6ab808d85a71d64710 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 28 Jan 2020 00:52:35 -0600 Subject: [PATCH 100/560] Docs: Update readme for new org-make-toc --- README.org | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/README.org b/README.org index b199954..6152f2a 100644 --- a/README.org +++ b/README.org @@ -12,19 +12,15 @@ It includes three libraries: The =org-ql= library is flexible and may be used as * Contents :PROPERTIES: -:TOC: this +:TOC: :include siblings :depth 0 :ignore this :force depth :END: -- [[#screenshots][Screenshots]] -- [[#installation][Installation]] -- [[#usage][Usage]] - - [[#commands][Commands]] - - [[#queries][Queries]] - - [[#non-sexp-query-syntax][Non-sexp query syntax]] - - [[#predicates][Predicates]] - - [[#datetime-predicates][Date/time predicates]] - - [[#functions--macros][Functions / Macros]] -- [[#changelog][Changelog]] -- [[#notes][Notes]] +:CONTENTS: +- [[#screenshots][Screenshots]] +- [[#installation][Installation]] +- [[#usage][Usage]] +- [[#changelog][Changelog]] +:END: + * Screenshots @@ -558,7 +554,7 @@ First tagged release. * Notes :PROPERTIES: -:TOC: ignore-children +:TOC: :ignore this :END: ** Comparison with Org Agenda searches @@ -577,14 +573,14 @@ This package is used by [[https://github.com/alphapapa/org-sidebar][org-sidebar] * License :PROPERTIES: -:TOC: ignore +:TOC: :ignore this :END: GPLv3 * COMMENT Code :noexport: :PROPERTIES: -:TOC: ignore +:TOC: :ignore this :END: # The COMMENT keyword prevents GitHub's renderer from showing this entry. @@ -646,7 +642,7 @@ If ~org-ql~ is loaded byte-compiled, the argument lists are not named properly ( * COMMENT Export setup :noexport: :PROPERTIES: -:TOC: ignore +:TOC: :ignore this :END: # Copied from org-super-agenda's readme, in which much was borrowed from Org's =org-manual.org=. From 6e3c0d3c68055d26b24ca671bb34811b9a3a855e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 27 Jan 2020 19:26:08 -0600 Subject: [PATCH 101/560] Add: Transient view dispatcher --- README.org | 15 +- images/demo-org-ql-view-dispatch.sh | 166 ++++++++++++++++++++++ images/org-ql-view-dispatch.gif | Bin 0 -> 1884495 bytes org-ql-view.el | 207 +++++++++++++++++++++++++++- org-ql.info | 120 +++++++++------- 5 files changed, 451 insertions(+), 57 deletions(-) create mode 100755 images/demo-org-ql-view-dispatch.sh create mode 100644 images/org-ql-view-dispatch.gif diff --git a/README.org b/README.org index 6152f2a..719c7a1 100644 --- a/README.org +++ b/README.org @@ -26,6 +26,7 @@ It includes three libraries: The =org-ql= library is flexible and may be used as [[images/org-ql-search.gif]] +[[images/org-ql-view-dispatch.gif]] [[images/helm-org-ql.gif]] @@ -111,7 +112,8 @@ Read ~QUERY~ and search with ~org-ql~. Interactively, prompt for these variable ~SORT~: One or a list of ~org-ql~ sorting functions, like ~date~ or ~priority~. *Bindings:* Keys bound in results buffer. -+ =g=: Refresh results. With prefix, prompt to adjust search parameters. ++ =r=: Refresh results. With prefix, prompt to adjust search parameters. ++ =v=: Show =transient= view dispatcher (like Magit's popups). + =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). *Note:* The view buffer is currently put in ~org-agenda-mode~, which means that /some/ Org Agenda commands work, such as jumping to entries and changing item priorities (without necessarily updating the view). This feature is experimental and not guaranteed to work correctly with all commands. (It works to the extent it does because the appropriate text properties are placed on each item, imitating an Agenda buffer.) @@ -128,6 +130,11 @@ This command displays matches with Helm. *Note:* Helm is not a package dependen Choose and display a view stored in ~org-ql-views~. +*Bindings:* Keys bound in view buffer. ++ =r=: Refresh results. With prefix, prompt to adjust search parameters. ++ =v=: Show =transient= view dispatcher (like Magit's popups). ++ =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). + *** org-ql-view-sidebar Show a sidebar window listing views stored in =org-ql-views= for easy access. In the sidebar, press =RET= or =mouse-1= to show the view at point, and press =c= to customize the view at point. @@ -395,7 +402,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience ** 0.5-pre -Nothing new yet. +*Added* ++ View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. + +*Changed* ++ Binding to refresh search/view buffers changed to =r=. ** 0.4 diff --git a/images/demo-org-ql-view-dispatch.sh b/images/demo-org-ql-view-dispatch.sh new file mode 100755 index 0000000..3e009b3 --- /dev/null +++ b/images/demo-org-ql-view-dispatch.sh @@ -0,0 +1,166 @@ +#!/bin/bash + +# NOTE: Run "setxkbmap us" before running. See https://github.com/jordansissel/xdotool/issues/49 + +# NOTE: should be bound to this function in the Emacs window, like this: + +# (global-set-key [f1] +# (defun gif-screencast-start-or-stop () +# (interactive) +# (if gif-screencast-mode +# (progn +# (gif-screencast-stop) +# (setq gc-cons-threshold gc-cons-threshold-original)) +# (setq gc-cons-threshold-original gc-cons-threshold) +# (setq gc-cons-threshold (* 1024 1024 500)) +# (gif-screencast)))) + +# * Functions + +function ensure_window_name { + if ! [[ $(xdotool getwindowfocus getwindowname) = $1 ]] + then + echo "Wrong window!" >&2 + exit 1 + fi +} + +function key { + xdotool key "$@" +} + +function input { + raw_input "$@" + + # Correct for Helm's input idle delay by sending extra commands to + # make the screenshots be taken. Not sure why two are necessary, + # but they seem to be. + key ctrl+p + sleep 0.26 + key ctrl+p +} + +function raw_input { + xdotool type --delay 200 "$@" +} + +function view-dispatch { + key v + sleep 2 +} +function view-refresh { + key r + sleep 2 +} + +function clear-input { + key ctrl+a ctrl+k + sleep 0.5 +} +function set-field { + key $1 + shift + sleep 1 + clear-input + raw_input "$@" + sleep 1 + key Return + sleep 1 +} + +function set-field-with-unique-completion { + # "$@" should be a unique completion. + key $1 + shift + sleep 0.5 + clear-input + key Tab + sleep 0.5 + raw_input "$@" + key Tab + sleep 0.75 + key Return + sleep 1 +} + +function complete-in-steps { + # Assumes input is clear. + key Tab + sleep 0.75 + key Tab + sleep 0.75 + + for s in "$@" + do + raw_input "$s" + key Tab + sleep 0.75 + done + sleep 1 +} + +# * Script + +# No matter what I try, xdotool is not working properly to focus/raise/select +# a window. And for some bizarre reason, the "xdotool selectwindow" command +# outputs a completely different window ID than "xdotool search" outputs. In +# fact, the window ID it outputs does not even appear in the output of +# "xprop" for that window. I have no idea where it's getting that ID. + +# So rather than cleanly selecting the proper window in the script, we have to +# do a hacky workaround by sleeping and checking the name of the active +# window. + +sleep 3 +ensure_window_name "data.org" + +# Start gif-screencast +key F1 +sleep 2 + +# M-x org-ql-view RET, TAB, Ov TAB, Ag TAB, RET +key alt+x +sleep 0.2 +raw_input "org-ql-view" +sleep 1 +key Return +sleep 1 + +complete-in-steps Ov Ag +key Return +sleep 2 + +# Edit view. +view-dispatch +set-field t "Space-related" +set-field q "tags:space,spaceship" +set-field-with-unique-completion g pri +view-refresh + +# Save query +view-dispatch +key ctrl+s +sleep 1 +key Return +sleep 2 + +# New query: Ambition +view-dispatch +set-field t Ambition +set-field q "category:ambition" +set-field s "priority" +set-field g "parent" +view-refresh + +view-dispatch +set-field t "Upcoming: ambition" +set-field g ts +view-refresh + +# Save view. +view-dispatch +key ctrl+s +sleep 0.75 +key Return + +key F1 diff --git a/images/org-ql-view-dispatch.gif b/images/org-ql-view-dispatch.gif new file mode 100644 index 0000000000000000000000000000000000000000..e76c5b7aa27f5d57a8b2cf91c3560cb03bbc3fc8 GIT binary patch literal 1884495 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�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

4y_9th&cr`|<9{jke|2?XGuBKQ`r| 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%0A-wH%oQ(^ogFEax;yxuPQBH^T~)W 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

15SX&b3F9*g+rIE8kB@0We%eIEsPt`7BU{h<9 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ðz{o^>Lm?Qj*fTtBl<(^a9YEJK%b9&dF(|him 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 z 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�&sKXu}pDa*Cyp+H>1V_PS|mMt$2 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

E*^T{4d-i^ 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⁢8YAMwT)@at;>f=(Rhj1iqd+?2nuo3j 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ⅇ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

T58Pd~2Kbz<4Z zZ3lDmAHKQB_SPqD2TOH(fk20|=G)8rIK(crt$LTmdgImVW$eWTQ?K@MidnE$O<<2% zv0G?DbC;FKb+_#F#Z9>q&3|vmKf5t=@dY6z$zJ~d5p5nFF>fPU7jhW2zS#3)!i3lt zY}T{5#UJ*oFU)&wH-%y5#Ki{rU*cH5#xZ{0A;cBf@NL=MNq^L(%d9 zUus2Ttiw#{4ZPX{EtwUQq^?hsUchQOf$49;r=)@++5RHi6NSkWnEx(V&bpvT`#Oi% zj7A5JHrX5ECw6>h|E{VMUew*uuXDfX>mpG)r0QKfHdGld^w7sDAUOj+|(H+uLzpZf2F_Rh9@V6}m3` zGGoJ+wevncn8v>H-!y6QQZ0^E|5vg7xZogl_?`TOCHxJ%>=RgR6PBD?T>7&>PBoIT z<;O=mgS~kVc}+K}Nlqx&T~J>Ao+VJ>gPCHZ+%Aq?>)!5^Ydu$89(et`=*87p?dhHe zvUAuAbElUqdhxC2M_HOfUgd@yY4)$z?Y5a=*1V@WnEThTi7?{y(bIznOXq ziJfH7b6?+ZUyN-*lfw0`bn_pT>%Ui<^NVU4-JSfyA>v!d`ih>4WwYG{WiM7-dsfl) zts<-Z|6_N%UdR2fDf549m#YzYU0qRbw(j}&_3wZ5 z-=CJF|2vmI`{}e!y%p?Rc9#@){Qh%I?5pHt9gbB=;oOr7RRk=)wue=P##gnp*Bspc zY5xBH76TS`p#0b3?>#f8r+2<@UbX&D+Ip_A>5UhD*IamR{o*FG z{QngNm(;3R1KtSMvx$~Z)$3rl5@-_5XRK0SHE^(F7063Gz^t)>x#5JU3*$kFdj*0% zD-0esNngr{v<&8X$fR|zXKSa?#Dr#xs}i0M7kRcZi5$)FlvM7W(!_sfi^YVc?oR4~ zTyAd)HgaF%6N9WVb)1&1Efp25+IrR`Lsm%2Wk*3)v(d2$6%xk0vw5Z)q+SvU{g@=J zezZvN$jZsf{hN3;m;`S=>~?F8b+w&oXOOD*0w+-cQ>#*ghlkqumHpOK7(PDMC-2;+ zQ)%?{)HMC%b88|$b9lbL*IHdQqt!Z?=ivqKxlwX6TXg)EnyE__NR)p`5w4jlHD{@4 z0KeM*vG_wD{^!~!4eUceI zQpaEBuWUDV`83UhJN#`zcG#V5HKLyHA0Ew~IDzA1rLqtEzrWvw60Ui=#|Av*+%~gC zI4ELat9a6kg>BMBHx{-_t6jg--r^|GQLVga#-c9mO*a;G>mQO>+#}w0B8e^EVdG(m zt4j@G;IaMKVHDjXl)%)P!c*{ZNxx-Hk&|fejh#1`8h)AG zV6MBc@dA@>!$OV4|0gqQX)NTdz2MW3Uvz8ba@S1@crEHpocc43^gb|$PqG#0Xsl4ksK7Ww?Q6#mC10J5 zuU@Uu6RKXBy!D>cob|$G+3K9LjApOf_1etM#pJ!hWj5=pdLoXxJ2Wq}+Ax*{^7FHN zoxLLO(}SXH?oTTiXWK05IdH~!U1oBZt?+GS_M_s-IsQ%>A(v-4op-%{ri6`;`E2N(*H&u1kx3%QkyB&V zjgKO1Q_d86Dn~b5IuU4@k;JO{e@e^57grWED7|5=n=tp=(&XuDFED9cVdPQ`WInd_ zdgT46bxuy3Z*RX}UtPdwl;lx#ZcnT0gAEzJCpNq9`^Oa1pTDrFxn1^_jZXmgmkj4F zfdGd`I$Ifz7rP!?p6nwKaQnxCfKd6?5N=QN3rg)GQeTfA;%Q{LEF7yVn%pDf_eSX| zuVrZG`{m&M|Gw^6e1NftE5pgAZ-Hf1 zieGE*9VTh11}(7V+R@>3qpo?^LFD`w%1 zRg2hVS|>EPb7=$$D{gMks#(Mw?0o3Tr41TZGF?K9R#ViXp3m|8m=zOTsqB2ALe5^U zOPJYm@phig3_5>UTe@OWW=TBgN)AYGX?0BG3;$su&ZbjnnR1X%w7}rF=8-sl<+B&% zoR8gHvP$w|)QRE_=6TsB?VX!FXI49G;4!)|Nm=F%gD;QCM)`u|sflkUI%PCX;MZ~H zpU~+bKF7^0Ig|5$DN=zk#N&MX(FxC5N>F~SBJccv}w zxnS#d$ar32(Gx=~iCvaPrEvEh!3C|5vuj8FlF@eku}q*V)*#C_Jbwt(o1iFfm!|f{8Ux0rv%wC#)KQ zzOjwn3Zfe_op${Uu-#-dr`u`~(;3N@Ir9vAJ0j;gKYe*+d06MXiASD?ylK_1{pj6h z$g<*a%Y)GMYO59mbB3z=O+0)&r=Vly9W_T4g`n*hjxX}{k@PQ1xGuX!VY=g;RDJ6Y zrxV`2Su!KaP1>qZ=~%=8es`Z&T#F=IX5AC%i#fc^tXj%%JHyxH{|{x-EzfseDb<_G zwWe7s)4N(lQ10BskkTugb9OXjPHbsgH&=}3te~E()D*>89qy0oemGxET-fbm^2q5< zm+q{RiCw;LIz%HQk81ZRb^FhmAvXK)X5ZR1{QCqRCyS*z=3Pr%*1vV7X|clbUA;#( zafCRmKf!tK-_MDA8(gMXO|6npymxKOueUpH7s|+am1Kp;x^%CqUa{f{c0Z-ojx9`c zj|X!F-&j0-${H2L>vK;rsfj5b|KcTV*1>S?2=~oTm(JI@|GEF~pM%529U;O23jY(L zA}%~pS1)LEDNtZ}IXk3G?DB>`vc@x`w=k3+^q$n#8Jsnb@#(D-&JxjQd2?PIoV_8c zV$H1$u1*$r5~uVonsTo3+{p*Z^Fxn>Ia{~7f-E8|v)77zmx9vFFYZb@#HZjNZj1jZ- z4dq?S8`w8D_#bheIV&+HPm%fJv!WF)?Wt#&Ji222Y_0bnx@Wds-6bc=)ak-hNk)+w ziMLM`IEd}vcA>Xu%i>bwHdY@ASIPTR7$ZA&-~M%Pd+NTw3-xaNyfrEE0MCi`g{r0} z{qLVTz0_dS%Pyr67r;Hs;`^3>at6g)F1QrJQodle>9yG;>?(Bv7CSXm2D?x+o`d6 zJQAqe*8cQ`Bd?9iD?{yYp3H)WS8ta5eJ#Xwb!E|GzV+ORW`Y*3H$@AWWY7G3p2|^` z+!e96W4oz8&p}Vgx;J0;Yj>OEmY=yMTx`%-T@)|+Dm<8f|BM~Kd0!;B^=uWLY`dS? z?sJUP!QJ-)i`GqFcK%z(@uzQcjvxB+x~MSE&xv`Oe&en`Uzw&pJixW=aLdKyM3&5^ zIZSc-X&)pLHnhjA2wMEVxYc3axt-hpzN_Z%%bxDQ7irIPZpmVk$-j8ge$4)&bW#a?2~(O;C+RH zeQQEqN7vJU1?q);&l~!hGn)-oG)kE;X{fUBCSK=gdhlMOfp-Igu}r*^ihN_N-!q#C zo^uPFTwIf0w0?eadYB ziz`orvzki3`G(`7_xubCZY4Z8B2v)&KjzOlrVR~#ALL_x&K2kL|F|K-P=i&NfoYH8 z1I2wDCv}f83mrKUG2?~LynPKp;#V%H{+-OHIPdXFKc1Zva_(M;RE^uL+M*%arPely z-;ec4r=NP*q6l6$p?l%3mVx3E4~VPA7AIbO@{vo-f>rckQb}opnCnIU68-=U4v(LU z@>3WL^jd^oE@BF~=d|RE+@|UO3y%o%KDKsMRw`QDqoMR->fIwpoCTKfz3NSFwe)-a zGv-n1qDO))YCGN3YcDnIWVX1_*sybv(~L(Niyk>S$k{wQ#y7FeR%~|C7tsWU$p(eu zjxR!^9B*332qK|ltd}6?&?`M*o9Os2>Qnt4{9Nrk(+PUbJ&JDGl&ihKAz5lD=_$N8MF>QyA zL#CZu{NJetoYP#(F0gtW%=>pP{E%q)gEaOFS7UEp4YcuyeRlP~M$MG(KhsRhCgy!o z^J07E^~uYdPrb0Mn{~#~Ev9MZaVL`d+Wg%3)Iy&ncqqNRF+qLbHLId!npWH)ZmB_^ zW~e=2JIl+K{_IZ3nmg4-ch4=2`QjU&7;;@FYI=gI@`8)8hMMWorA*;68G1(Hm6w*< z&S)>PW%adaEi_zFAnN92^h6`zu_C8<@z>`Pu~W(yWwf?5Fu65r-e}PrO`$v;)uX8yM3|zcFr7e_n%E* zl8~4)!AqibE5jr$&B;m+!1D;;zpLR5&YGqE+SfOVFhYp{>c|L%n>Jqs@v z2CWDTi8g(3kfVlCnr(6DmX~27DneY-qVBjxi?o=A^dG$VvU{#$k7uIxjdM~F&Z)VeKSc33n-;myOg-g_(Rt~sCPboM+nbI!))0ZESqvh++*SaV1+=djhA!%jIzyxtrM$~hYK=4jHInIGcb zaW?#Vxqw zP`U#13Z*{1CvTi`)~vlZ?@-5~&|_>fe0^+J#I4eD*gGlKiQz?3L676p;}TcSXx-sD zpCW%jpx5nf;@7M4-~RIadokbqL;R^VJ&hlD9YuUKZP#53TDPmh!G!0WaLA#IS79~| zPMW)zdD<9lS>|(*3Dj)9^ZdBP>BZa1rm>$HC{^HXU0O71-EhaP?fr%l1$A8~9d;7cM_lBz)1W zUqV-;Kr;55)P`?KdXhiZ+%|Dk&R~97))4yk^0G6F7iTd2nw31!s!zl6MyA^_24*(V zC0EXc9A3tAIbp#Y$7NgztQ!=$o*ie{V7S%AXs55U><8ZcCxuIN_mnJEe0xpMrQyb- zYiptm*rJ#Dr#)45U7OTUFlkP~=0ye_YA(f2$q{VNxW9`q6hHC0TJZJJ2l4eMXSyEF zl5=xpHQZ;w$145ur_)&9?@jmSfHPV`8*g7wzp^S{)r&j-qJra<+@y|-v#ufi zdtASEEj97_Xu9syzh$59tts;V>bN)XV%b6II^80@?vs2An&fO6rRF#@OU+hmIIJQv z!+K6Mcgs4dp1haO9y=aomgR6%nVsHu=-rK^8ErS$CFMMhNN91}aa{X;OYDZDM$<7vEWz^Z)i2y<<<&PNox0PtN3oeEDCl!coS{QDJg%nQ!a*tHqw#GMfY4 zwyoq7?a1y4iC(sHi|6StM<&kRIrT--5@|!#lRYP-_llm{JM)bXx9JAPJD(%j4ocqf z+ih|<_GpMh%w@jP5bv)c!CQM;4uvL{hGl;ZD=rPM{uPlI- zws~>&H$5HZZ13{o=UVHm{?c?&u^6z2O4{6P5wqkHLTGL#a{#84}xggs#Sn4qIW#;1PPTDuv zD$>mg)|Y7-FsCt>r(8a4CQuQUz9YAwLc_tLqT!#1rGhibY@vsYV$ZT=Bf&1A5p zLR;mqrhVbC&4;pP;h(ADKU$|BDnIW$e>Zby@zzD3%N7e;E)xH> zDA}~|15@PjCR2eQ%Y=8#v9{8!VK(47JbiN6^zRjm>?=&x9MAx)R?3$DObKT^!HPa6pe6X5$|B!Xf;dRW`6W3R*-oL9myu8GJ z`|RZEZP~xKJ^orJzN4Yra<%f#4q>Y;%I3jVyIP}n?NZ;h(BG=fST!|xM|l1AJ-e%Q zXY8n!w>GO}!{og~UI~nQxIjnE9?mm-E$dA75 zJN|FFy>rfetBKBkTGl&RcbFfm-ZR&HPa(6-sebG2n`=(*{&V`X>74tOCJx^Z-?j{A zwkqC#=t#r&(BsvO?{}ZS++4BSdiVKijXyT)c3WTizNgXHyrubDWd66U>0ht(muj*w zPuS1guU>O#_xB=ki?iN4Pgw6+CBFT-|IR(>wafi#Zl#xMci65u%xqZlw@>{0$@Hzu z^S9nRTyy{T-}{?)ZcqN&zj)i(e(QPD4{4w9Ojox(?7i#4<=TtNRh7iU|y{(nyHce>MlXv+ERbL!pB-u@f9-1Y^3^Na0!kM7@lt^U}= z{rj#z{=4*e`Mv*k54ivT{~-K-wsu?i;o7s!yThd`3e;;Kzux_s|L-2@zfZsKxfE@6 zx!kNpzvAHRty&?~SKI%G&#!xU+xF#s+Z)MWUrw$#asInDkMp1Te_t>EcW3(k!yi)|M@G619=gy0SXug@jv=#Azv~&V?FLdv;7rcJG&WY!k7Zl;SyA zJ#bmb&Pl1>)AbXNO{olW^qp;9sP*ARf$X8Mi&a%Rq1|$ZZ7#iSPFfp9Hdn3}vQmwB zo#~wWd6}5+iZxls7e=+0)gC=FclQ#((34G8Mq#GC!gup>SaWh$%s(u#ud8gsl~rW{ zvU)i`CS-1EUCOh6Z-l_Sz}EHep54tZ6#c(v7w2Tw)GUF8PThQpMR&IP6t1|qG<{jv z-dUyD*ViW=pJp4K;&|UPD1P9xX7OWxe*)6D_VCw z-JAI6aJOw^jqn<3Jdg@#}GBa=Y zTjgI@7}bogsAN60sCs6Zt+_0!uzlVl9j&L9Rofcoaz*wkB9{am)_ z+2=J*z4x{VTZFDL)E9AJwY_-3SsZQHNO(KLt16vmt%+|err}(0;`IPj9q1W%0 zKkN;^SNYO*;@#?xXT$H;{(O7=emx^!#Dhjoy&Dgj1^pr(wo2yRc-XGk7xAc5bKQ+c z-G=8P9`{{ojTd&t2?GO8+-|c+4?)JOgAJ0X<-~033?f3f``C~pTe5-lq!(l=H zn2$##^Y45-uGk;*>7?fRJD*M)o{#x_*7E(G&*vTaW4~PV)W7@Xa-e_g*Q=5FcfVdw z?2r9+GjsjjZ?_B2$9}(C`Tp+r`;Gi@KOT1K-}~`+qJP}ar!({K{d~T#KknDdmFw^Q zdcE;{-0!zL-{1TF{vdz+pN}W?@BjIH(Let0*PHqG|9*eiAOG*?%k}sF{r-49{{P>f z@9+Qr&nV%*$oGFj1FOjcM!^{lta=j~c}pHJD@r(W`b}sO-SU9daE2pq-h^h^FAvxq zC7cBNCbX!UJmd_V;Uv0lLaT1cL+(TgXUTH~g@+eBIZd75M^N z4jSB%nxwch(c@6T3Xd3pP6=1dPyOw!#Yqp{E?8(rOf2-A^GN()#eOZba~*BWZ2Wlv z$8>Kc^Cp%&mcDuY*dfP@h2c6f{Kq-mZQot2Ik@29(~1|IN1jgXZ#7x+HRB`8$%Rd9 zy*ViluRZ9p-l8aMzTmN<;mniIE13jaLheZA9khu0b5U;Ll_#2koqNot33e|@QPJcs z=hpBz$lDV!M>cq-cdS8lKB;<>XPzy2X1q|+H`8zO zER{Dc<{NJEoDw}OeUoFZd7?P4-lTP+nJb=IKE2MF9MdQ0(s0N;{(4*a0wp*li;BvBF}>-t0^_eyQO5otNdha_%^bhWC^z<*`^B+~Lb< zu!!8UnWJ7~j$iSvF4I|;3#?=3s@!ngnW5m!V^%xIOw^s*(nFE!s6mXp0DHiaQ&ZOL zHg-6ot)x55~dgbF) z2SW~vUMpzVb+Z$`e*Nmv&{gVl=P2uxM;sG-x1s*4&U>qcJemfHn>(d*o|&Awc*t>E zfvB%+h$C+|jfwy;a8Bc;Su- zL3u}2zJ2U(lu1$KpLxR7?9;@Fb5d0GXP)#e`^0!!(@vr}Pvl0-vA+3pQZH@%R%knS zUi0h9=ySb?R_>o#n7?&S+6mDqHR58iUi{m`P0!yfxR{ag@LXe%rT)7u{jWDa{1A2P zW}x`Kz+9O*yy?&E&GR-ind#2uy~Vau%#W)rPbTj7>nqaPzY2CwWfIRS+~L5I%&xa^13wl(i=a1`@ZYq&Aij5=6l-N))#I4Yn`loZr8o7$1V9j zzNt3myV#noeNZs3;Q6blLWz341Iso2GQIg$|2&#oHTn6o3!!)9s!c7Q#Qobbqj}CO zuBkC?kvvJv>gT3e@_%f2{2)^=gQ@Ur0CNDl?Rf+Lb@#fJix<`ID?ak|P64af$A>+A zUlzam^U7rYvm=RbdsCl86xy1_v`eO!9sZYhYVzrK3)h}WJ+ktyTt>XiUD@{X_3!7t zul@e}KBIiaLH>Ckv|0{56r5jiRDa&b-ts?>73C{W`p^3`b^D*EhVv`W=Fj^)_xqpc zj`CF(|M$=Pvef+V%fR_nSDh0J)|UT$ohV;@^ZdMTywZ-!B`ka%B@dEfSFrO-sWJLE zD5)P(|94R00ISUoou8+VpJbo4uyu|@{I9Ls>)t8{bXWK=@%J*c^Hlw>Zqt3heuLq^ z?}_}n7Fz{@Ll10E-*{g)$7BJ|r~RCN-`3au-M^3f(~V}|k_Ugaj(u;)PgGeT?6L5N zfI;FTe}>RyjKxhXi}ab)3;yc_6eu}}pGjoRS2nFuW}~my9w^4Xkw& zLU%E+emuZ;=b@xk0^@@Pa_98f)*n!dYLGMf7|B&Ac=0^Pwu2J+N^E-=#q%DqZRuLw zrO3Fsfcx(S?(hW0hy=E@vsbd1SmjQ09dnRU`Dk|If^^eCwx9&@If0A|3Rmx1CF8k3 zx~+?&%Zt&@Vfm8-oHs7=_x@K9%v``$)+n`oqjc_rf4>-{WC9qa6coiT2`O&Mi#QNh4xFIg|(|4FTBlDg*t z$@lAdHY5t3%$IIb;9fXMvHa8D2||B29FRI&#Lb=GrS?f=vp-AdC)IqV-)Wmzo;v<= z`otPuq-A@7Gykwkwv*mweh&3dKYp+>-O5)KH2yF5l<}N`&4!m!DGeIyKXUgQ8RkA> zIQ@Zr2P0=z5~G`f$^Cxb%?lYk7f3Dnf8J2>vb4%(H9uqCJSCobA(m;4JgY7$_XaVZ zx}>&5NPS6>?otlnY$uLc2mUinR(T#I-nLOcbR)x8BNf{K{s1FU+YdiD3{?1qjq{TX z<%Kj>CT#CWVBbW&BzRBBX!TkD?YHzU9-ylYXFMqp)^@9t=6Ak2k z2wCP|aPALQZQUT`cTny7QpL(kY9U*!3zKYbPh{M5;EzVI8^4LIsW7+YWn<9?OiLcP z^Izh>eL*7GfirQ7TFMr?_Zxm?De>^@?cB7{M*Dv;t6+%7p3GX@tY=!MqaQGXE4Ywa7x~wde%fvZ3{=@?X5v~JVC(KE z#6Q8U{(!b9gCYMG{!jgyM~(dFezHz9*4SHQ%eqx~$`*S`p}k=f9M@iSSQ!#1FQjg6 zs##vdx@Ahoru^R@9tf*VvCLNzao;GSy-C-90p}e?-*iK{tdC-`S6E*zlq(Yz&t1e> zH`PB|DE`i5&s?R*;zR0@TX=dHIc*YnmO1`)aF9|u8Gpn1xN zX~`xGTymcZtsms4YA7%;DE?$&Wnxfb(BWcWXV}Tq!PF|P>m*|wB4ZpaYZa!ZW2GAx zspk`598~OVViKZf5 zZO*RBK7TCvQnB@o*m1k$0C28NdC3boq=Y6?Z3ms0uLRj{u4`z zPUcwgpIb47Gc?Tg`pRoF?(*%9SYP3zH~ajHEmd<_HsAlSqsDLj?e{`Ah z<}F*dZQrqT*X})g_w7G$@X+BSM~@vpaq`sZGiT48zi{!=E6YTjf>qYWei*YMC7ZSoU9SND(2*-rKhJGB%hk&xp~>y*%rmG z?ws7b{QUp<4$WM$URzdNT+PdoM>Q_t?E_Q8QeSLkx;VxP4 zZEwUkXIx$tdwSd2+uI8spPK8vecj#N6`x<-J-vN>d}a_k>p$-ui&h@$2wy2P=Z0=_ zb-(oS-ZOoho}At-S9~T(a`W@jx%S<8qO*KnUR=@5Yd3e-*4NiJB%hw=yL;Q)+dGP1 z-#fc|`}_L`nz`lu_U!oh`1b^D`D0Oq3!j}{>^EprTzZg_1Vnno`<+*rf=wcR+;A{oUT*6FZ21_if1dI&#U?N^7;G*wo^|9 zHMz20EbPzA91Ne&{MmP>egnJSj|VN{c|RU@sIU9+sK@->kH-_-^?p8? z5}x<->5TMsKcCGhe^>d)zFzOwizU%>7mrwh$zIutnEJq|tY*wCWkvydzN z#33;~rMirU#DJ8JnZl2n+ENcJ^e>UnmFqg#Zq4|p>(Q}(=DasNPC6|Dxij{zius^6 z#ZZu!SE*CQ?@$-Z$pksG9XvXR&PvDe1W80I9x>!Q*yGe8FU7m@n97zy_xv7bnO*~T z^)>%D_H`b3EIDz(@hJu$#cFF@6z+Do#Ih7kF#7peN8luf+oi&ZHD?l~WGt1vo)z*> zd*Y(@v|{1*(7@!08NrHQH=OK?Tr}lS;1cfelc&OVeVV%A%4{u5#cgg^jHd07xg(ss z+|{PQaQXorHK(+hPDxy!XPh|FWjOidnKY}CLO1Yi;jGVdWHr^TuAe+tw(IlU4`=!~@-;cCe!b)QCgW^(eZ%>RU&ea-r9&L0 z9FG_-m=u=r=vf1cpkV30&kMOqGT2qQE_OwQNQ>-U;bwm7Vqevl#R|MDJ>0!6O`7#( ziH7e=ukcfsrtSK&^uIyxN}qJE%d>7>v69@o(y#o~<$1qEvg~ zyS}b1=v^K2-0S+TTVL1d{ahutW?A^2U!@u0rYxcVy>1+m`nI7%Qz1$G^o?Uy-!@Ko zIx%T>Sl>yvZ<_+L7N;ieiZpr<5X94PB*8hv;YsPWxl4PO1o(6NpY@u$Rj2i>wYhfm znOkBr7Vlk~SAP07-#62!)2nrbTXy?B+GbFz_~M>-vo`Bxvy1fw2J2pM?AZS-t8wSG zCGP}pT(?n_GT$)qvR=vJ3z09k3GMdN_`lx%;%%1aaphbujq~5!u#Pb~v3>iGv+L`= zpN>zuD7tF@Tm3WdvM>IdtGM&viQMfS-U%^>1h(yFeqVX8+@`OM|BzO$feY`M5MJ&d zhxI}XI^2C8iF@u?r2a0U%XLGNC{ti>a7H0l{F+-DF9MG7Ecqz-tj$^O{l)pV|2`_W z`gkb)H$IWM#;|+lgU9lZB^rFgobDv#JdqWCc#^Z{)1=%rPt-Dgo(QYUo78@RQO(LvGseaNplXPKgD~U&;yvCx{>W>AHjGPn`oJ!@1nj>(_S)xHIpU-SDAdwLq}Kj_Y8BH8mDVSRkBJ}4V|qTv0O81ovu%SURpM|b_9_4D4 z*d3cX^K|;o7a5Z`W_nuY_y^>#yiib(U9jz0xw~cC>6ab7{Zo31H=cg7d40jL-lF3Z zLQZVka&qhBv#YW%t;o1>a{AZJfj>_qQ`o#?`+s06q7i4Nd0|Dd*IFyhYir6*zpdK; zU<0%f7d10t_vRblt@V%^aR~w8CEl&t?Jmvkovwl1U2YSi+9!8-PIE3{>FAuA=2Y2V)NJIeYHB-x~Ma zMD7dM3+5;8zAKbP`d_w{X2SoCJmMZuLU z22-~f8@-k|Q~vtg+8ryGJv;q>hLzyoBRe;(2neL{u?z%lYis z@bGYluy)*;9UC7XpP=kL&u8bRr>AEaXWu)sbMy1_3!J;bSGm8gUny zE;Rg>vpbeBdBYw~t@}E6B8wkgc&pIwcVx%2=X*AoU-aAin=AA3Uj8Gl|EdZ;zE~b1 zoNQ*B_AdW{^2GQ1{%QT*^pgEje|*i4e``K|Z*O3zN{?;iP+Re!iN_3YBTi*n#-mP+ zWh)+a>1=4K3?OnxUZnz^6oen zF~O&DOujE$r%Fd=sz^jcwW)}{?liiV8J!mRO!oX-Pq*p88*cW@EnD&zao|AQaS%lw#;*EQ_2uxE}6I@EwQQbd7<)57Z#6r8?7Ug^vVifNY7@wv{Gum z(|1+L#c8j6R>Wk@TDp*7+N`$Klllyott=}LSll1x^HZJO>%l3O`d#0+UJ0&H3tW@Z zGRaFj>3GquH=8dAarU@Sy4&uQy?(p>L7Vow9Z#lZzuWm@+3NrAcD>p5 z`rYmi$F%e7Qh!*z-&^`6a;|vqqSW;pez4V?-P-^6_TmE^?2FzDu*hH354I{xEjT37 zZT?YEJbaB|p`>`Da=Ajjj!~|x@JGXA8vScNozmI<=F@3|<2s+um|V~KeAeRmn$PEK zzQ6f=-ho~B%LSMG9lAp9;=ODMF$uF=BEHXf`bEGeI`G_;lW%vvw~5ladvs0Jfm2C` zw^j7cUV2or@tbV+a<^}X9xt_RV~m^dce7Ehu;5CW>c@{?EJYGXeIl#F!y_>9>W@OKc6pX*8?@;@_xNsvHaZI!>d4zID_dtyLT6eANjvN zVbl4#^>@3UuG_t9>*v1T?~km1QvLD7=|UTMMd^(-pEx%0eGEQZ&GYx`jr8?@zuhT+ z|M&ZYcKv@po=ngG_wy51|G!^vw&%BgDXMw7V@fX59@np%!`HGtb#++#UGPuwghxBt z><(Ym^!MXPkYKyf{xk4kx^)^GhuEv)3T^HOuP&GizfEqg z`j8+T@?zgR8IM{YheWxE9V}AY&NO6Ccu*_Aayawqc@7&RiGLHqto}ykiRk()5}JPE zh?>>M&VZgpBFjCFYDInQia4`KY`es|=Y@sJZZ?Yq6P7yMWLeJ@_a`agP?Iz3N4;K- zCgqbNix0n7`TwHFGDtbqC(ucCilB4R7GH%@;}eHZ7&x_FQI5J*vB*Vhl6c~j!}9W; zC%vLRO`36LiJJMzlYUj7CNJPwx?M)oYth6_Q=F_-XDKcA3Nd5sk7<}M92LnP)plsw zx;0Mxha0@jzX%EJKchO|Lc-kO#HWNt&SmmbG|yE0=$onCpe9kHde%6^xcj<{vsw7b zQ&S@Kr{8{(YJU9Z*&?&gb6)r?hd1JSmfJk{JRfB6kojv(OtsMj|Fa7h^(plP$^Kj6e9a|P^oP{>xzASfuHsa=GXuB;HRetU;b;-KK={I(D znJw8h)honBkz=J-;M6C_mrrDyHtB#%#C0Z7EsLk(hd7S;m;`#R`1EkX=M!0yUs?p$ zc_dA8SbIF^ffrjtovUgL!)oO-9|d;K64h%CJv4Vq(-loM?fg1lCwXz^h>Sg{8eti0 zLXB2lSN2DajsyOT@e_iwX4*1q3Y_e&52>VQ$#oH$judre|_cN zuW#EA@UAOp_rCK;>idopsp0N3FNmGq_jz+qz#zE7%%6$|6dj&hCIx;tkt zM|r8ZXW@jxg&_w2J<6n&Z|LZh>xE}zRqz^K`?0RSS5WG`S&-5Ft!|Gbub0NkE_{7+ z&)@a~g;&?>b!J)zraajn(W&db?f7xQI6b-dx<09b$-)b+sBT^~SE=c@d#hlz>!HhQ zbyfE)nCPVuxT{9{V~Y__+%|(nTk~#iaOPm#>#;9!Z`6a_qIRDrO45>(-2FC9nm%Xm zOuvICBX6t_&^eHj<0#1!w9crL$%d6dL-BOfyy??B8J-zTUvWm_sgujaoV4=Z$i=y0 zpQk^L(XE@5z#9IKY4%H*Mb^Ow&u4`(E%@n!+=wggUBJo5VKh@?vLm~zLrmp9=OvRr zq^XxkMOO(GW&PKSZS&uqefh$ILMflMN+HH=SKcIbx&`+R`i15_MC)l^_&Mf zo2I$1fBPZ3-(=wpuLEBNC!DoN4L)%*_J_$Dc@LHh?S;(B0i|2F3*@N3*u`}@?a&ry zg%;*D3^F&CeVo_5AXmAE^Vq@}S2yf5c(24`edm>@vGAGLKHKQu9DmMT**|$NOHK98 zd!7Yf4;@lkw?JmsiDeKEh{ zOYaFg1rp*|dz`B{xPMg0n!WvB;%|NId5uHqwe1gzHfH~gR&Dq!KBKN}LB2G9PdGU619=o6p2{fuS_6*h zJbc;R!gJV;e=)!7hr z^8DiPJGNKg)!DylDODUC|NjY?J@{qC^Z#mc!vD#W73!54svf$EANo0W!rw3a@28hSdIrTl-jTuF2WtN4u!sU3|nHyY)BG%83m zDOohBL^P>YG-=Fe(%R9abE8S`N0Wg>vynx!Nkp?*MYF|>W~&Zf_8raV)wsBKG)N1! ztbfuRa-q3Op(T`|G5A1>=Ykfu7c8gJk~{+HoETa!B(!Qbv<9xIah2eT`5{u+-eTF2 z{j;5|P`xFwf;a0%D^ED9*^}I!jcs`yRSgYUE$;291#M9c?Y;}zOK;SsD5UH>&{~xt zt5;t0l(B>NL}P4w^>22zhwAJTIoMX2cSZ+vHty)0bE9+KkIn@WU5hHDKTHemeZjtP znRIfJ>{1EYs2O(66T9|o3|T87E5*<-$3ko~liAi8EdMPGwWpS`?Um^9bm$3r&{7mo zJnyN}*AHfsgxTs;yB8F6)ftE#n-S%~kSsZ+GNHKFTOoF@2g~gWmU}NOUnTPj2{24_ zW!cD}d~rv@$^!Pa#oFUV=gcgzejnLg*|%mtFOOn!7}RZOf(m>`-ot7^%tiiTO@k7h1f zDG_p$XNjiISqsOHC*&GKr(C}<)jNPM-NN)tL-vfyyyye79vAoBUpR5XVS_W8nJ>Tg zoZ#fz%*j^X$s)=SbXn8M*q3oa++K9d_I^Op}Xk7R&$N zo{=JnEY~|l6&d|2PqI|soStODD)=j;xsX4MV|Lt)LbWJXm0cN%QnU4bEi#Z=Y-F|A zWR|A7CY$*y$w;x884EfrPqAzMlKA$LO*l%y{uitJDalKZXQwzMduGWyYc1k9rQm;x zHB?I}e3$tB$xEl6SnRT()0JV_Ob-^*=P93dnk8AW1Wa4X_;Jpw%(~PA%UFwM@18mP zLd0@KO@5zQHQpZ>t8Xn2ov^G@VTIR&<#7`hx9m!GR#={zup(rGO3y9%Q@tPGqczKCm4vj@w+49UPO|GSox*k>)D9=Ixa)zst(nK@dk zyR%rg{VM*?q&c&qVYN5I8s7${Ym+9v$efdUVNoRK>d6ziLw}huGo+oBSiAGp>Q66N zvVW~kj#_(sCrexw+o4%3=DQ{sELkx58qbfD39qykPAC+Xo3{9!7cYnF3UPVuQ}6g^&%ecd6kZg?o}H-7&a?iV>YK1Nqj9TF z@+Q+;TjPFjO_1J}WW6mVTkZcwj(Mrxs_E9N?+9(md$4U`WSI*?cFK=!c?~&!$7_G6 zciawVea6*&jceZPuYEbcdFs1ZVpLn5HpHxR+uqGREiPlZD<|L9o!pnUW=ei5JlL?a z%bMk(nd#A=I+Lqb`UcA`iQcjP)k5B5l0~m~*34!Vw_+`*Zi!s5J@mp3o6W0y3i$7J zZu(^@^|fL5#M|4an{W5I&AQo|^^kVnsq8(6qYHOtuaWLtQ@eG`^;2s~zO=3Ty{B*Y zUY`#cA2YX~Tvd55y5Q{Yy%n4GXl~snwRpF&xLQp0UcS|myO!^Bd%mZ;eSba2f}Pu| zqnGdhD}CT+^uF)j2iWcyv2ZQC_IlNulM?l(_x=z4zH95x17fH4dt6wso%=w1!hRoz zc9A`L{85{@_w4%IEg63B;B)UimmOHdqxcxrM3V&rHF%PQ*5tR823Swt;(1}AdyDBu z>+lZ73~jE1Ar0H5YW8dFVs++8%t$!GZX^2t@m}LI?Pto4Xdh^Id2MOG#$;pm+_*X0 zWE;667?cfzj-}Nc%b0U4YtJ!5rDLoIkLA2M_Ky2l$cL5nmsgj}IbOBr_|7SNqyx7z z@7i|bv|#&b5eb_EpG=OY1uPLLI?-_Ec-@DC3lg&Xduq1ab}6~Fc2f88wC-IUjB^-V z4(opJiMqfh8=(AtL*@em(=a2R)&o1eOm@xBTG?WK;>zk1+(YJa2jSD%qV!dtxNZ*3>@KX6t*i=XT9W ztvhyy_b|QOwPye8lU)ywKNc@Nb?3Co^D|%CST5?Ee=_-iQqQ@SuXoQ}cslsO`7bi( z?{QyRqKahl+$Hyx*`y=Cpg} zbc)!Xa}l_-E&Sr=Ek`HZxuo~^l7Z}HqqiXk-z<8n!*-L0ZKBw&_8v*wy?*9<<6o`W zoB82#)`4@S30FdQTv3=U?cvM4@V1iaT$cAa`{Fln!z(wP+i@~3;IwKDo1eOH$UY<83kJ(SNKGmwb+d78z(T7t%tZ&9gsa)MK zXLHW3lHN_Tb{))Ka3$lxac1@t>vCCQc>6D=pV!)Jmf~Ab9ZC(e*Il<*s*JCf-vArLru;=*Q8xPmA|I59)d;wc# z?){Vn?F?tH{gL7L|GZ|?ncUN<0aZ86Z>KrT+RAy)|3&e`Y4(F-3O;k|qAu5uITv2=suo|pO3}dH+*L0 znB~c{+`xGn6(G?|xCAGTk=`Y8Fq)d_Kr!sgU>&SUedc{E8PV^)r&POK77pTzQe zyesEP%!;%r;yJ!S?)4_S*IVLVZ;Lzje|_ESUHe||*>|kyPUHVtiGzK-hvg(SY%iaf z_vX~TH)rm>Irs0)1-ZAE?A~69dwZ?!?TvYFZ|!?~=ib|U|K2{3d-v#E#%|kpOW0fL zEm|Zjwmt1@OJ#T}w(3prjVpq0*w4AiXG=Vrx1-?Q?pLX68$RW+{F?Xfqu+-HgV{pQ z-*0?bRG9JM(}E9+Zobo;)BbAT-9+g#jhP)4t61K*RtxNZFF2jW$htnLu^Jnuu zY3=`{bN`dx|4)^ISI%=wf6!am)N{vR{^vWB%VR#&Z8xlBeo-2j8)Fk6#>XzDtY6OQ zvBJ|n#g(5cBkTlUvxMV$_OyG!{`Sw$KB(ky{wejZ6&v)*#`u_j>$o}7x_4|2ot%9o=+#;EU{Y{_;O0r*0_!TBi~ND z{k863;>Q^=X7ev*ew}ruXf<)(Y2_Ch8=siG)$M0gaO&!a!t%=M%FND&jV--$ zDtgA<8at-V%$sV~)xUYx)~LnvYPW9Rd0uQuNBg1hW0OxU&*^rV;ncJ0YWK0={fAAa zT{ZB=dn#=={yS?=7}O&>bur>xa^pid|aDrdqc>f z38%JdomUb#bmPd9ql%ig$EH{ccY0W;XlLDN3gT#V&|djriRF|G_t|-2uTo~ZW=PD4 zYtYO5zjIM$;Og*N*{_QdZ%xY3?+&mDF6F##ATU*ICReLY*!Fzqsh4*-HBMN!_*&o3 zSx@c?N9Bg6T)6Z-c}f9ur%mhb85@`GjC%fyaZl2Ek@*S7pTrvNEKEN?pS6_1c2-H| zWoNzh5o+H`vahdCUDjqhyDazi_QL1a_RcQPzrVkcU0iR)yAOt3yQISR#dth%3Czq+ zvzuEb@#5;n^!HcJ8BBWQbx5*Ud9O$6+vgXZt-jm(+!DRh`ht7gA^Dv(K^*ddZ(77Q za{5hbUS$7##tZ$u%$7<1T&%4L27RwjG;kc!iEzH)^h$=Mzk_F|@`Mh~g$#l-RkUoB z4>;V}9dNYCDCX!Ak^j96US>*Zdz3^arh6=yBi#LwXh1Txne+ za_J;s76@CJa$0 zxR)Mtb)5U|vgWrZOB(_LeM7H?M&@3<8lKo2dMz?@t!P*h%hN;NMu!ewz7}8ld1@EW zQJ%#&UV5>Hg(m*|bI8w7so2kE?-qtB9U^N>+d@)zE;+8R+9#^iYH;l_`~#5o4sVCDUrEv~Ex8|^V*F`I4>hCY4nNdzD~(t&^Yjh= z=ac5zSl;Ok77KW6ckOIbimDp(mkh0G&t{&U93E!*LMQH7(kTaqwX0qjZIX5JT%Ni3 zdy-O-Xw?g4i6h*(Tb6U3@R<7EYC8w(w!B5LD(6zf->bQlwLjMS#d`bd$|$B;zREHs z>t6MIZ(RIZ^vfS%PWxD)M=wqs+%dc8pk+C4ppM=9n37ce*oA?$NSBWvvD*j_PS&|mVCIP%kEK zr@Ly;rpYcGsX`rJPAN^9#51FW`Du=&x7vkIQ}%l;RSC5`>9k5{+By}ra!&;wjNtT5_9~inCqm75`tvi%LX&0ZK2fvov$PD45uSbhx2n?aNDrkI3Uk-?xaghM zJbKplGRIP%G^4c_JnRk_&r3h@TxK(wE+eQo%FNO<88T^`&p& ztl+utrYyJp`qKY@qg2R3zNsr*OM{HX8<*wtU zW=ae8#%bG~*4Jgp$0k`jTX`ZkT z%GY+cJk~mRaQ2LXR{1|&ocfvK(sE4|#(z5M-ga*jc@wWLWAsSn$ZGljJN!FpA3ju0 z*dZj&X4s>~U&izi*&-r=!)S~x-_f}YHI_wn43_B$MJ0#8W{LFKu+dj|zIOln+ zNdNiTZ=dHg%4Rt7&$`fR_GO{q+>8e=ch+{5eOV+~%i6~E=;G9Ou}gT9GJT)(U5-1T zD0a=MC(t9|@=~*}D+A|dg|44)OJ(*|G0uT|ZL&_4k3N zEphy_ZyYuIwsB%?W}?g)$H{d!S#Gdfts8Au#f9pxM}VSzj(!# zdEdT0TqTg_(tn%l>9ch&uheFh1q-!tOqSl&YmjZwqJ8i0x9|HI=Ee6(-IkE4e33VZYCJeK|bkmDDZrzQ0FJB)||A}Mjob`W#THmpZc^RwL<-FckpmV+?_kP8? z_cibTA6S5xD7Tt_VMU48+Nkw6)|8$8I(65B4HY?mCV^Hvp3U10UhP;e`ELL2nJenQ z<<^(NS38V-cU^ zycLhS@|K=>)cv28>2XiO4v)v^s~ug$GM`NJP+R$Ak`HLLW57RW$0;FUo;RnYI~-u0 z_P8KZj3q9ulXXUN!V9;E#CsE#ab_R8k|q;%PavHuU(D&5Zt1cq&&8@Q8Km>pzq+6< z)XWyVf~&o5$_vHDz6&e3%h|SQL`@d@_(FQ>yGbiKW|w)oFAs>3VqIY|ahJ=I{~fy) zuGCtwi+Q!@4lZrp&T~LfU7PqIlS2FvIbDOOF=DY&V)~#VDwBIxu@oDoL z8dWH)o=~_@cd~->S>-)v;?KyLA1vlpoL#s{c|C zv8`vf9t&tXr=D|``Fg;Uoh4}=t7BR&YA&10a>M_;Vd?FHIqeD*`F@6Nx=&D@6e0`D*L?%#6Veck7OcexiZuzMU} zlKSBK{jv*FdQ;^6@0D>YmE)KfzgHS3_=S^D&O|X`FL( zCz>e9wB6`3Jfas87;UQJB35tOtuFVWJAr4h#Bq;f|BYsS?8)$1EOq_FF|%DCdkcCN z%RKiuZguOU<8!0y+mEqr(>=GEw~i%9q1506|3mMHw#5(S7$tR^UQR5n+tjpzOLM+c zP>^5w8OTJr)9bEzJWK5zB73~6+NK;aNKFs0ojj?lx)CYQ8BNvF(BXfh|n8CwR&xbNNrZp}9!VGSS;rX@Y-eOFw_7<}#0>j@cbb zAzzawm`Yg⪻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 ;; Url: https://github.com/alphapapa/org-ql +;; Package-Requires: ((transient)) ;;; Commentary: @@ -69,7 +70,8 @@ down a chain of function calls would be awkward.") (defvar org-ql-view-map (let ((map (copy-keymap org-agenda-mode-map))) - (define-key map "g" #'org-ql-view-refresh) + (define-key map "r" #'org-ql-view-refresh) + (define-key map "v" #'org-ql-view-dispatch) (define-key map (kbd "C-x C-s") #'org-ql-view-save) map) "Keymap for `org-ql-view', `org-ql-search', and `org-ql-views' views. @@ -334,14 +336,26 @@ update search arguments." (defun org-ql-view-save () "Save current `org-ql-search' buffer to `org-ql-views'." (interactive) - (let* ((name (read-string "Save view as: ")) + (let* ((name (read-string "Save view as: " org-ql-view-title)) (plist (list :buffers-files org-ql-view-buffers-files :query org-ql-view-query :sort org-ql-view-sort :narrow org-ql-view-narrow :super-groups org-ql-view-super-groups :title name))) - (setf (map-elt org-ql-views name nil #'equal) plist) + (when (or (not (map-elt org-ql-views name nil #'equal)) + (yes-or-no-p (format "Overwrite view \"%s\"?" name))) + (setf (map-elt org-ql-views name nil #'equal) plist) + (customize-set-variable 'org-ql-views org-ql-views) + (customize-mark-to-save 'org-ql-views)))) + +(defun org-ql-view-delete () + "Delete current view (with confirmation)." + (interactive) + (when (yes-or-no-p (format "Delete view \"%s\"?" org-ql-view-title)) + (setf org-ql-views + (--remove (equal (car it) org-ql-view-title) + org-ql-views)) (customize-set-variable 'org-ql-views org-ql-views) (customize-mark-to-save 'org-ql-views))) @@ -419,7 +433,7 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', "Return `header-line-format' for BUFFERS-FILES and QUERY. If TITLE, prepend it to the header." (let* ((title (if title - (concat (propertize "View:" 'face 'org-agenda-structure) + (concat (propertize "View:" 'face 'transient-argument) title " ") "")) (query-formatted (org-ql-view--format-query query)) @@ -436,9 +450,9 @@ If TITLE, prepend it to the header." (s-truncate available-width)) 'help-echo buffers-files-formatted))) (concat title - (propertize "Query:" 'face 'org-agenda-structure) + (propertize "Query:" 'face 'transient-argument) query-propertized " " - (propertize "In:" 'face 'org-agenda-structure) + (propertize "In:" 'face 'transient-argument) buffers-files-formatted))) (defun org-ql-view--format-query (query) @@ -484,6 +498,128 @@ dates in the past, and negative for dates in the future." (format "in %sd" (* -1 difference))) (t "today"))) +;;;; Transient + +;; This section uses `transient' to allow the user to easily modify +;; and refresh views. + +;; NOTE: I don't really know what I'm doing here. Even though the +;; Transient manual is written very well, not everything is covered in +;; it, so I'm having to try to imitate examples from `magit-transient'. + +(require 'transient) + +(defclass org-ql-view--variable (transient-variable) + ;; FIXME: We don't need :scope, but maybe a slot has to be defined. + ((scope :initarg :scope))) + +(cl-defmethod transient-infix-set ((obj org-ql-view--variable) value) + "Set Org QL View variable defined by OBJ to VALUE." + (let ((variable (oref obj variable))) + (oset obj value value) + (set (make-local-variable (oref obj variable)) value) + (unless (or value transient--prefix) + (message "Unset %s" variable)))) + +(define-transient-command org-ql-view-dispatch () + "Show Org QL View dispatcher." + [["Edit" + ("t" org-ql-view--transient-title) + ("q" org-ql-view--transient-query) + ("i" org-ql-view--transient-in) + ("s" org-ql-view--transient-sort) + ("g" org-ql-view--transient-super-groups)]] + [["View" + ("r" "Refresh" org-ql-view-refresh) + ("v" "Select" org-ql-view)] + ["" + ("C-s" "Save" org-ql-view-save) + ("C-k" "Delete" org-ql-view-delete)]]) + +(defun org-ql-view--format-transient-key-value (key value) + "Return KEY and VALUE formatted for display in Transient." + ;; `window-width' minus 15 is about right. I think there's no way + ;; to determine it automatically, because we can't know which column + ;; Transient is starting at. + (let ((max-width (- (window-width) 15))) + (format "%s: %s" (propertize key 'face 'transient-argument) + (s-truncate max-width (format "%s" value))))) + +(defun org-ql-view--format-transient-lisp-argument (key value) + "Return KEY and VALUE (a Lisp object) formatted for display in Transient." + ;; `window-width' minus 15 is about right. I think there's no way + ;; to determine it automatically, because we can't know which column + ;; Transient is starting at. + (s-truncate (- (window-width) 15) + (concat (propertize key 'face 'transient-argument) ": " + (->> value + org-ql-view--format-query + (org-ql-view--font-lock-string 'emacs-lisp-mode))))) + +(define-infix-command org-ql-view--transient-title () + ;; TODO: Add an asterisk or something when the view has been modified but not saved. + :description (lambda () (org-ql-view--format-transient-key-value "Title" org-ql-view-title)) + :class 'org-ql-view--variable + :argument "" + :variable 'org-ql-view-title + :prompt "Title: " + :reader (lambda (prompt _initial-input history) + ;; FIXME: Figure out how to integrate initial-input. + (read-string prompt (when org-ql-view-title + (format "%s" org-ql-view-title)) + history))) + +(define-infix-command org-ql-view--transient-query () + :description (lambda () (org-ql-view--format-transient-lisp-argument "Query" org-ql-view-query)) + :class 'org-ql-view--variable + :argument "" + :variable 'org-ql-view-query + :prompt "Query: " + :reader (lambda (prompt _initial-input history) + ;; FIXME: Figure out how to integrate initial-input. + (let ((query (read-string prompt (when org-ql-view-query + (format "%S" org-ql-view-query)) + history))) + (if (or (string-prefix-p "(" query) + (string-prefix-p "\"" query)) + ;; Read sexp query. + (read query) + ;; Parse non-sexp query into sexp query. + (org-ql--plain-query query))))) + +(define-infix-command org-ql-view--transient-in () + :description (lambda () (org-ql-view--format-transient-lisp-argument "In buffers/files" org-ql-view-buffers-files)) + :class 'org-ql-view--variable + :argument "" + :variable 'org-ql-view-buffers-files + :prompt "Buffers/files: " + :reader (lambda (_prompt _initial-input _history) + ;; FIXME: Figure out how to integrate initial-input and history. + (org-ql-view--complete-buffers-files))) + +(define-infix-command org-ql-view--transient-super-groups () + :description (lambda () + (org-ql-view--format-transient-lisp-argument "Group by" org-ql-view-super-groups)) + :class 'org-ql-view--variable + :argument "" + :variable 'org-ql-view-super-groups + :prompt "Group by: " + :reader (lambda (_prompt _initial-input _history) + ;; FIXME: Figure out how to integrate initial-input and history. + (org-ql-view--complete-super-groups))) + +(define-infix-command org-ql-view--transient-sort () + :description + (lambda () + (org-ql-view--format-transient-lisp-argument "Sort by" (or org-ql-view-sort 'buffer-order))) + :class 'org-ql-view--variable + :argument "" + :variable 'org-ql-view-sort + :prompt "Sort: " + :reader (lambda (_prompt _initial-input _history) + ;; FIXME: Figure out how to integrate initial-input and history. + (org-ql-view--complete-sort))) + ;;;; Faces/properties (defun org-ql-view--format-element (element) @@ -671,6 +807,65 @@ property." (face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) +;;;;; Completion + +(defun org-ql-view--complete-buffers-files () + "Return value for `org-ql-view-buffers-files' using completion." + (if (and org-ql-view-buffers-files + (bufferp org-ql-view-buffers-files)) + ;; Buffers can't be input by name, so if the default value is a buffer, just use it. + ;; TODO: Find a way to fix this. + org-ql-view-buffers-files + (pcase-exhaustive (completing-read "Buffers/Files: " + (list 'buffer 'agenda 'directory 'all) + nil nil (when org-ql-view-buffers-files + (let ((print-length nil)) + (prin1-to-string (cons 'list org-ql-view-buffers-files))))) + ((or "" "buffer") (current-buffer)) + ("agenda" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("directory" (org-ql-search-directories-files)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else))))) + +(defun org-ql-view--complete-super-groups () + "Return value for `org-ql-view-super-groups' using completion." + (when (bound-and-true-p org-super-agenda-auto-selector-keywords) + (let ((keywords (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + (pcase (completing-read "Group by: " + (append (list "Don't group" + "Global super-groups") + keywords) + nil nil (when org-ql-view-super-groups + (format "%S" org-ql-view-super-groups))) + ("Global super-groups" org-super-agenda-groups) + ((or "" "Don't group") nil) + ((and keyword (guard (member keyword keywords))) + (list (list (intern (concat ":auto-" keyword))))) + (else (read else)))))) + +(defun org-ql-view--complete-sort () + "Return value for `org-ql-view-sort' using completion." + (let ((input (->> (completing-read-multiple "Sort by: " + (list "buffer-order" + "date" + "deadline" + "priority" + "scheduled" + "todo") + nil nil (when org-ql-view-sort + (prin1-to-string org-ql-view-sort))) + (--remove (equal "buffer-order" it))))) + (pcase input + ('nil nil) + ((and (pred listp) sort) + ;; Multiple sorters. + (mapcar #'intern sort)) + (sort ;; One sorter. + (intern sort))))) + ;;;; Footer (provide 'org-ql-view) diff --git a/org-ql.info b/org-ql.info index b0e6fad..2f9951d 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.5-pre: 05-pre. * 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. @@ -93,9 +94,7 @@ File: README.info, Node: Contents, Next: Screenshots, Prev: Top, Up: Top 1 Contents ********** - • • • - • • - • • • • • • + • • • •  File: README.info, Node: Screenshots, Next: Installation, Prev: Contents, Up: Top @@ -216,8 +215,9 @@ Interactively, with prefix, leave narrowed. ‘priority’. *Bindings:* Keys bound in results buffer. - • g: Refresh results. With prefix, prompt to adjust search + • r: Refresh results. With prefix, prompt to adjust search parameters. + • v: Show transient view dispatcher (like Magit’s popups). • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with command ‘org-ql-view’). @@ -251,6 +251,13 @@ File: README.info, Node: org-ql-view, Next: org-ql-view-sidebar, Prev: helm-o Choose and display a view stored in ‘org-ql-views’. + *Bindings:* Keys bound in view buffer. + • r: Refresh results. With prefix, prompt to adjust search + parameters. + • v: Show transient view dispatcher (like Magit’s popups). + • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with + command ‘org-ql-view’). +  File: README.info, Node: org-ql-view-sidebar, Next: org-ql-view-recent-items, Prev: org-ql-view, Up: Commands @@ -703,6 +710,7 @@ releases. * Menu: +* 0.5-pre: 05-pre. * 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. @@ -714,9 +722,22 @@ releases. * 0.1: 01.  -File: README.info, Node: 04, Next: 032, Up: Changelog +File: README.info, Node: 05-pre, Next: 04, Up: Changelog -5.1 0.4 +5.1 0.5-pre +=========== + +*Added* + • View dispatcher using transient.el (like Magit), bound to v in + search/view buffers. + + *Changed* + • Binding to refresh search/view buffers changed to r. + + +File: README.info, Node: 04, Next: 032, Prev: 05-pre, Up: Changelog + +5.2 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -797,7 +818,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.2 0.3.2 +5.3 0.3.2 ========= *Fixed* @@ -810,7 +831,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.3 0.3.1 +5.4 0.3.1 ========= *Fixed* @@ -820,7 +841,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.4 0.3 +5.5 0.3 ======= *Added* @@ -885,7 +906,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.5 0.2.3 +5.6 0.2.3 ========= *Fixed* @@ -895,7 +916,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.6 0.2.2 +5.7 0.2.2 ========= *Fixed* @@ -906,7 +927,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.7 0.2.1 +5.8 0.2.1 ========= *Fixed* @@ -916,7 +937,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.8 0.2 +5.9 0.2 ======= *Added* @@ -999,8 +1020,8 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.9 0.1 -======= +5.10 0.1 +======== First tagged release. @@ -1057,40 +1078,41 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1402 -Node: Screenshots1576 -Node: Installation1694 -Node: Quelpa2332 -Node: Usage2775 -Node: Commands3124 -Node: org-ql-search3597 -Node: helm-org-ql5245 -Node: org-ql-view5657 -Node: org-ql-view-sidebar5855 -Node: org-ql-view-recent-items6211 -Node: org-ql-sparse-tree6695 -Node: Queries7495 -Node: Non-sexp query syntax8403 -Node: General predicates10110 -Node: Ancestor/descendant predicates14917 -Node: Date/time predicates16045 -Node: Functions / Macros18700 -Node: Agenda-like views18933 -Node: Listing / acting-on results20338 -Node: Changelog24940 -Node: 0425469 -Node: 03229388 -Node: 03129765 -Node: 0329960 -Node: 02332933 -Node: 02233159 -Node: 02133425 -Node: 0233622 -Node: 0137655 -Node: Notes37754 -Node: Comparison with Org Agenda searches37916 -Node: org-sidebar38788 -Node: License39067 +Node: Contents1422 +Node: Screenshots1545 +Node: Installation1663 +Node: Quelpa2301 +Node: Usage2744 +Node: Commands3093 +Node: org-ql-search3566 +Node: helm-org-ql5280 +Node: org-ql-view5692 +Node: org-ql-view-sidebar6189 +Node: org-ql-view-recent-items6545 +Node: org-ql-sparse-tree7029 +Node: Queries7829 +Node: Non-sexp query syntax8737 +Node: General predicates10444 +Node: Ancestor/descendant predicates15251 +Node: Date/time predicates16379 +Node: Functions / Macros19034 +Node: Agenda-like views19267 +Node: Listing / acting-on results20672 +Node: Changelog25274 +Node: 05-pre25823 +Node: 0426090 +Node: 03230024 +Node: 03130401 +Node: 0330596 +Node: 02333569 +Node: 02233795 +Node: 02134061 +Node: 0234258 +Node: 0138291 +Node: Notes38392 +Node: Comparison with Org Agenda searches38554 +Node: org-sidebar39426 +Node: License39705  End Tag Table From b601a1e7779253f2d9cf9ce3f7640f57259a4767 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 2 Feb 2020 03:28:58 -0600 Subject: [PATCH 102/560] Update: (org-ql-view-save) Require map 2.0 and use map-elt I upgrade to map.el 2.0 (from ELPA) locally, which deprecates this TESTFN argument. --- org-ql-view.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 312686c..6cd4bce 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Package-Requires: ((transient)) +;; Package-Requires: ((transient) (map "2.0")) ;;; Commentary: @@ -343,7 +343,7 @@ update search arguments." :narrow org-ql-view-narrow :super-groups org-ql-view-super-groups :title name))) - (when (or (not (map-elt org-ql-views name nil #'equal)) + (when (or (not (map-elt org-ql-views name nil)) (yes-or-no-p (format "Overwrite view \"%s\"?" name))) (setf (map-elt org-ql-views name nil #'equal) plist) (customize-set-variable 'org-ql-views org-ql-views) From 9580c0ef670ba9768c1d9e0c0f153d96268e6f68 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 10 Feb 2020 09:09:54 -0600 Subject: [PATCH 103/560] Change: (org-ql-search) Use new completion functions --- org-ql-search.el | 45 +++------------------------------------------ 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index d97d59e..10d3fcf 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -139,51 +139,12 @@ display the results. By default, the value of `org-ql-view-buffer' is used, and a new buffer is created if necessary." (declare (indent defun)) - (interactive (list (if (and org-ql-view-buffers-files - (bufferp org-ql-view-buffers-files)) - ;; Buffers can't be input by name, so if the default value is a buffer, just use it. - ;; TODO: Find a way to fix this. - org-ql-view-buffers-files - (pcase-exhaustive (completing-read "Buffers/Files: " - (list 'buffer 'agenda 'directory 'all) - nil nil (when org-ql-view-buffers-files - (let ((print-length nil)) - (prin1-to-string (cons 'list org-ql-view-buffers-files))))) - ((or "" "buffer") (current-buffer)) - ("agenda" (org-agenda-files)) - ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) - (buffer-list))) - ("directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) - (else (s-split (rx (1+ space)) else)))) + (interactive (list (org-ql-view--complete-buffers-files) (read-string "Query: " (when org-ql-view-query (format "%S" org-ql-view-query))) :narrow (or org-ql-view-narrow (eq current-prefix-arg '(4))) - :super-groups (when (bound-and-true-p org-super-agenda-auto-selector-keywords) - (let ((keywords (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6)))) - (pcase (completing-read "Group by: " - (append (list "Don't group" - "Global super-groups") - keywords) - nil nil (when org-ql-view-super-groups - (format "%S" org-ql-view-super-groups))) - ("Global super-groups" org-super-agenda-groups) - ((or "" "Don't group") nil) - ((and keyword (guard (member keyword keywords))) - (list (list (intern (concat ":auto-" keyword))))) - (else (read else))))) - :sort (pcase (completing-read "Sort by: " - (list "Don't sort" - "date" - "deadline" - "priority" - "scheduled" - "todo") - nil t (when org-ql-view-sort - (prin1-to-string org-ql-view-sort))) - ((or "" "Don't sort") nil) - (sort (intern sort))))) + :super-groups (org-ql-view--complete-super-groups) + :sort (org-ql-view--complete-sort))) ;; NOTE: Using `with-temp-buffer' is a hack to work around the fact that `make-local-variable' ;; does not work reliably from inside a `let' form when the target buffer is current on entry ;; to or exit from the `let', even though `make-local-variable' is actually done in From d8dec50f5cbf40dc7f5c0a2ee78d4a9e0a286a9c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 10 Feb 2020 09:13:30 -0600 Subject: [PATCH 104/560] Meta: (.gitignore) Add .sandbox --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 28f3b16..784a564 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /scratch.el .cask /sandbox/ +/.sandbox/ From 87b483e4e406405abc08dec30eac02c7228cad11 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 11 Feb 2020 06:54:19 -0600 Subject: [PATCH 105/560] Fix: Require transient in org-ql.el I guess package-build only finds dependencies in the file named after the package. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index c41abd3..ce574aa 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql ;; Version: 0.5-pre -;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: From 048de35b07d8d29fc6fa49c34d7ba1fd1c912011 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 13 Feb 2020 00:45:01 -0600 Subject: [PATCH 106/560] Notes: Add idea on partial property value searches --- notes.org | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/notes.org b/notes.org index d082ce3..b5ae904 100644 --- a/notes.org +++ b/notes.org @@ -602,6 +602,17 @@ This works okay (except the priority accessor needs to be fixed, because Org pri e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. +[2020-02-13 Thu 00:42] Something is needed to help search property values by partial matches. For example: + +#+BEGIN_SRC org + ,* [[https://github.com/fniessen/org-html-themes][org-html-themes: Framework including two themes, Bigblow and ReadTheOrg]] + :PROPERTIES: + :author: Fabrice Niessen + :END: +#+END_SRC + +Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. + ** MAYBE Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. From be696ff07568bde46988855bd8e94f6bcb092812 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 23 Feb 2020 22:59:49 -0600 Subject: [PATCH 107/560] Meta: Update makem.sh, etc. --- .github/workflows/test.yml | 14 ++++---- Makefile | 2 +- makem.sh | 68 +++++++++++++++----------------------- 3 files changed, 35 insertions(+), 49 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6930896..c3ec60f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,8 +28,8 @@ on: pull_request: push: # Comment out this section to enable testing of all branches. - # branches: - # - master + branches: + - master jobs: build: @@ -51,18 +51,20 @@ jobs: run: | SANDBOX_DIR=$(mktemp -d) || exit 1 echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR - ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --install-deps --install-linters + ./makem.sh -vv --sandbox=$SANDBOX_DIR --install-deps --install-linters # The "all" rule is not used, because it treats compilation warnings # as failures, so linting and testing are run as separate steps. - name: Lint - continue-on-error: true - run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint + # NOTE: Uncomment this line to treat lint failures as passing + # so the job doesn't show failure. + # continue-on-error: true + run: ./makem.sh -vv --sandbox=$SANDBOX_DIR lint - name: Test if: always() # Run test even if linting fails. - run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR test + run: ./makem.sh -vv --sandbox=$SANDBOX_DIR test # Local Variables: # eval: (outline-minor-mode) diff --git a/Makefile b/Makefile index ce9cdd8..17abfe0 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ ifdef sandbox ifeq ($(sandbox), t) SANDBOX = --sandbox else - SANDBOX = --sandbox $(sandbox) + SANDBOX = --sandbox=$(sandbox) endif endif diff --git a/makem.sh b/makem.sh index cab8458..3fddb78 100755 --- a/makem.sh +++ b/makem.sh @@ -90,14 +90,14 @@ Options: -C, --no-compile Don't compile files automatically. Sandbox options: - -s, --sandbox [DIR] Run Emacs with an empty config in a sandbox DIR. - If DIR does not exist, make it. If DIR is not - specified, use a temporary sandbox directory and - delete it afterward, implying --install-deps and - --install-linters. - --install-deps Automatically install package dependencies. - --install-linters Automatically install linters. - -i, --install PACKAGE Install PACKAGE before running rules. + -s[DIR], --sandbox[=DIR] Run Emacs with an empty config in a sandbox DIR. + If DIR does not exist, make it. If DIR is not + specified, use a temporary sandbox directory and + delete it afterward, implying --install-deps and + --install-linters. + --install-deps Automatically install package dependencies. + --install-linters Automatically install linters. + -i, --install PACKAGE Install PACKAGE before running rules. An Emacs version-specific subdirectory is automatically made inside the sandbox, allowing testing with multiple Emacs versions. When @@ -400,7 +400,7 @@ function dependencies { # Echo list of package dependencies. # Search package headers. - egrep '^;; Package-Requires: ' $(files-project-feature) $(files-project-test) \ + egrep -i '^;; Package-Requires: ' $(files-project-feature) $(files-project-test) \ | egrep -o '\([^([:space:]][^)]*\)' \ | egrep -o '^[^[:space:])]+' \ | sed -r 's/\(//g' \ @@ -423,10 +423,12 @@ function dependencies { # ** Sandbox function sandbox { - # Initialize sandbox. + verbose 2 "Initializing sandbox..." # *** Sandbox arguments + # MAYBE: Optionally use branch-specific sandbox? + # Check or make user-emacs-directory. if [[ $sandbox_dir ]] then @@ -451,15 +453,12 @@ function sandbox { # Make argument to load init file if it exists. init_file="$sandbox_dir/init.el" - [[ -r $init_file ]] \ - && local args_load_init_file=(--load "$init_file") # Set sandbox args. This is a global variable used by the run_emacs function. args_sandbox=( --title "makem.sh: $(basename $(pwd)) (sandbox: $sandbox_dir)" --eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))" --eval "(setq user-init-file (file-truename \"$init_file\"))" - "${args_load_init_file[@]}" ) # Add package-install arguments for dependencies. @@ -488,15 +487,16 @@ function sandbox { if [[ ${args_sandbox_package_install[@]} ]] then # Initialize the sandbox (installs packages once rather than for every rule). - debug "Initializing sandbox..." + verbose 1 "Installing packages into sandbox..." run_emacs \ --eval "(package-refresh-contents)" \ "${args_sandbox_package_install[@]}" \ - || die "Unable to initialize sandbox." + && success "Packages installed." \ + || die "Unable to initialize sandbox." fi - debug "Sandbox initialized." + verbose 2 "Sandbox initialized." } # ** Utility @@ -684,6 +684,7 @@ function interactive { unset arg_batch run_emacs \ $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ + --eval "(load user-init-file)" \ "${args_batch_interactive[@]}" arg_batch="--batch" } @@ -827,7 +828,7 @@ function test-ert { # * Defaults -test_files_regexp='^((tests?|t)/)|-test.el$|^test-' +test_files_regexp='^((tests?|t)/)|-tests?.el$|^test-' emacs_command=("emacs") errors=0 @@ -892,8 +893,8 @@ elisp_org_package_archive="(add-to-list 'package-archives '(\"org\" . \"https:// # * Args args=$(getopt -n "$0" \ - -o dhe:E:i:s:vf:CO \ - -l exclude:,emacs:,install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox: \ + -o dhe:E:i:s::vf:CO \ + -l exclude:,emacs:,install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox:: \ -- "$@") \ || { usage; exit 1; } eval set -- "$args" @@ -930,32 +931,15 @@ do ;; -s|--sandbox) sandbox=true - # Check whether next argument is an option, rule, or a sandbox directory. - if [[ $2 ]] && ! [[ $2 =~ ^-- ]] \ - && ! rule-p "$2" + shift + sandbox_dir="$1" + + if ! [[ $sandbox_dir ]] then - debug "Sandbox dir: $1" - shift - sandbox_dir="$1" - else debug "No sandbox dir: installing dependencies." install_deps=true - # HACK: Next argument is another option, so prepend blank arg to the - # argument list so it will be processed by next loop iteration. getopts - # doesn't allow options to have optional arguments, so we do this manually. - if [[ $2 =~ ^- ]] - then - # Next argument is an option: process it next. - new_args=("" "$@") - else - # Next argument is not an option: put it on the end. - new_arg="$2" - shift - shift - new_args=("" "$@" "$new_arg") - fi - debug "Setting new args: ${new_args[@]}" - set -- "${new_args[@]}" + else + debug "Sandbox dir: $1" fi ;; -v|--verbose) From 69692a4b9b4f0772fc663b24a07c64d77b071c00 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 23 Feb 2020 23:00:41 -0600 Subject: [PATCH 108/560] Meta: (.gitignore) Ignore scratch.org --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 784a564..ad6347b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ .cask /sandbox/ /.sandbox/ +/scratch.org From 32c68d7f249e1780a7e1a0b1155db3f36d535e1c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 23 Feb 2020 23:22:11 -0600 Subject: [PATCH 109/560] Fix: (--pre-process-query) level predicate with args in plain query Fixes #96. Thanks to Akira Komamura (@akirak) for reporting. Released as 0.4.1. --- README.org | 5 +++ org-ql.el | 12 ++++- org-ql.info | 103 ++++++++++++++++++++++++------------------- tests/test-org-ql.el | 10 ++++- 4 files changed, 83 insertions(+), 47 deletions(-) diff --git a/README.org b/README.org index eabd92a..e7c43e2 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.1 + +*Fixed* ++ =level= predicate used with arguments in plain queries. (Thanks to [[https://github.com/akirak][Akira Komamura]] for reporting.) + ** 0.4 /Note:/ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be renamed). Users who wish to avoid those changes happening unexpectedly in their configs should avoid upgrading =org-ql= beyond 0.4 automatically, as they will be pushed to the =master= branch when ready. diff --git a/org-ql.el b/org-ql.el index 2eec565..6008e8b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4 +;; Version: 0.4.1 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda @@ -583,6 +583,16 @@ Replaces bare strings with (regexp) selectors, and appropriate ;; "h" alias. `(heading ,@args)) + ;; Outline level. + (`(level . ,args) + ;; Arguments could be given as strings (e.g. from a non-Lisp query). + `(level ,@(--map (pcase it + ((or "<" "<=" ">" ">=" "=") + (intern it)) + ((pred stringp) (string-to-number it)) + (_ it)) + args))) + ;; Regexps. (`(r . ,args) ;; "r" alias. diff --git a/org-ql.info b/org-ql.info index 1915891..1a6a498 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.1: 041. * 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. @@ -703,6 +704,7 @@ releases. * Menu: +* 0.4.1: 041. * 0.4: 04. * 0.3.2: 032. * 0.3.1: 031. @@ -714,9 +716,19 @@ releases. * 0.1: 01.  -File: README.info, Node: 04, Next: 032, Up: Changelog +File: README.info, Node: 041, Next: 04, Up: Changelog -5.1 0.4 +5.1 0.4.1 +========= + +*Fixed* + • level predicate used with arguments in plain queries. (Thanks to + Akira Komamura (https://github.com/akirak) for reporting.) + + +File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog + +5.2 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -797,7 +809,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.2 0.3.2 +5.3 0.3.2 ========= *Fixed* @@ -810,7 +822,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.3 0.3.1 +5.4 0.3.1 ========= *Fixed* @@ -820,7 +832,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.4 0.3 +5.5 0.3 ======= *Added* @@ -885,7 +897,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.5 0.2.3 +5.6 0.2.3 ========= *Fixed* @@ -895,7 +907,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.6 0.2.2 +5.7 0.2.2 ========= *Fixed* @@ -906,7 +918,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.7 0.2.1 +5.8 0.2.1 ========= *Fixed* @@ -916,7 +928,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.8 0.2 +5.9 0.2 ======= *Added* @@ -999,8 +1011,8 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.9 0.1 -======= +5.10 0.1 +======== First tagged release. @@ -1060,40 +1072,41 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1402 -Node: Screenshots1576 -Node: Installation1694 -Node: Quelpa2332 -Node: Usage2775 -Node: Commands3124 -Node: org-ql-search3597 -Node: helm-org-ql5245 -Node: org-ql-view5657 -Node: org-ql-view-sidebar5855 -Node: org-ql-view-recent-items6211 -Node: org-ql-sparse-tree6695 -Node: Queries7495 -Node: Non-sexp query syntax8403 -Node: General predicates10110 -Node: Ancestor/descendant predicates14917 -Node: Date/time predicates16045 -Node: Functions / Macros18700 -Node: Agenda-like views18933 -Node: Listing / acting-on results20338 -Node: Changelog24940 -Node: 0425469 -Node: 03229388 -Node: 03129765 -Node: 0329960 -Node: 02332933 -Node: 02233159 -Node: 02133425 -Node: 0233622 -Node: 0137655 -Node: Notes37754 -Node: Comparison with Org Agenda searches37916 -Node: org-sidebar38787 -Node: License39066 +Node: Contents1417 +Node: Screenshots1591 +Node: Installation1709 +Node: Quelpa2347 +Node: Usage2790 +Node: Commands3139 +Node: org-ql-search3612 +Node: helm-org-ql5260 +Node: org-ql-view5672 +Node: org-ql-view-sidebar5870 +Node: org-ql-view-recent-items6226 +Node: org-ql-sparse-tree6710 +Node: Queries7510 +Node: Non-sexp query syntax8418 +Node: General predicates10125 +Node: Ancestor/descendant predicates14932 +Node: Date/time predicates16060 +Node: Functions / Macros18715 +Node: Agenda-like views18948 +Node: Listing / acting-on results20353 +Node: Changelog24955 +Node: 04125499 +Node: 0425726 +Node: 03229657 +Node: 03130034 +Node: 0330229 +Node: 02333202 +Node: 02233428 +Node: 02133694 +Node: 0233891 +Node: 0137924 +Node: Notes38025 +Node: Comparison with Org Agenda searches38187 +Node: org-sidebar39058 +Node: License39337  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 982e226..bf2340f 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -216,7 +216,15 @@ RESULTS should be a list of strings as returned by :order-by 'date)) :to-equal org-ql-test-num-headings))) - (it "Query pre-processing" + (describe "Query pre-processing" + (it "level:" + (expect (org-ql--pre-process-query '(level "1")) + :to-equal '(level 1)) + (expect (org-ql--pre-process-query '(level "1" "2")) + :to-equal '(level 1 2)) + (expect (org-ql--pre-process-query '(level ">" "1")) + :to-equal '(level > 1))) + (expect (org-ql--pre-process-query '(and "string1" "string2")) :to-equal '(and (regexp "string1") (regexp "string2"))) (expect (org-ql--pre-process-query '(or "string1" "string2")) From 9a56141f6c2ff2b8c6f92f93a218f4935b8f0335 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 23 Feb 2020 22:58:08 -0600 Subject: [PATCH 110/560] Add: (link) predicate --- README.org | 2 + org-ql.el | 141 ++++++++++++++++++++++++++++++++++++++++++- org-ql.info | 50 ++++++++------- tests/data.org | 2 + tests/test-org-ql.el | 31 ++++++++++ 5 files changed, 204 insertions(+), 22 deletions(-) diff --git a/README.org b/README.org index d72776a..21f48fe 100644 --- a/README.org +++ b/README.org @@ -198,6 +198,7 @@ Arguments are listed next to predicate names, where applicable. + =heading (&rest regexps)= :: Return non-nil if current entry's heading matches all ~REGEXPS~ (regexp strings). - Aliases: =h=. + =level (level-or-comparator &optional level)= :: Return non-nil if current heading's outline level matches arguments. The following forms are accepted: ~(level NUMBER)~: Matches if heading level is ~NUMBER~. ~(level NUMBER NUMBER)~: Matches if heading level is equal to or between NUMBERs. ~(level COMPARATOR NUMBER)~: Matches if heading level compares to ~NUMBER~ with ~COMPARATOR~. ~COMPARATOR~ may be ~<~, ~<=~, ~>~, or ~>=~. ++ =link (&optional description-or-target &key description target regexp-p)= :: Return non-nil if current heading contains a link matching arguments. ~DESCRIPTION-OR-TARGET~ is matched against the link's description and target. Alternatively, one or both of ~DESCRIPTION~ and ~TARGET~ may be matched separately. Without arguments, return non-nil if any link is found. + =outline-path (&rest strings)= :: Return non-nil if current node's outline path matches all of ~STRINGS~. Each string may appear as a substring in any part of the node's outline path. For example, the path =Food/Fruits/Grapes= would match ~(olp "Fruit" "Grape")~. - Aliases: ~olp~. + =outline-path-segment (&rest strings)= :: Return non-nil if current node's outline path matches ~STRINGS~. Matches ~STRINGS~ as a contiguous segment of the outline path. Each string is compared as a substring. For example the path ~Food/Fruits/Grapes~ would match ~(olps "Fruit" "Grape")~ but not ~(olps "Food" "Grape")~. @@ -404,6 +405,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Added* + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. ++ Predicate =link=, which matches descriptions and targets in Org links. *Changed* + Binding to refresh search/view buffers changed to =r=. diff --git a/org-ql.el b/org-ql.el index 0af9c5f..0853659 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql ;; Version: 0.5-pre -;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: @@ -73,6 +73,25 @@ That is, \"CLOSED:\", \"DEADLINE:\", or \"SCHEDULED:\".") Tags are stored in match group 1. Match group 2 stores the tags without the enclosing colons.") +(defconst org-ql-link-regexp + (if (bound-and-true-p org-link-bracket-re) + org-link-bracket-re + org-bracket-link-regexp) + "Regexp used to match Org bracket links. +Necessary because of changes in Org 9.something.") + +(defconst org-ql-link-description-group + (if (bound-and-true-p org-link-bracket-re) + 2 + 3) + ;; I wish Org would not introduce backward-incompatible changes like this in + ;; minor releases. It requires awkward workarounds to be maintained for years. + "Regexp match group used to extract description from Org bracket links. +Necessary because of backward-incompatible changes in Org +9.something: when `org-link-bracket-re' was added, +`org-bracket-link-regexp' was marked as an obsolete alias for it, +but the match groups were changed, so they are not compatible.") + ;;;; Variables (defvar org-ql--today nil) @@ -727,6 +746,40 @@ replace the clause with a preamble." (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) nil) + ;; Links. Always return nil, because we + ;; shouldn't need to test the predicate. + (`(link) + (setq org-ql-preamble + ;; Match a link with a target and optionally a description. + (rx (or bol (1+ blank)) + "[[" (1+ (not (any "]"))) "]" + (optional (seq "[" (0+ (not (any "]"))) "]")) + "]" + (or eol blank))) + nil) + ;; NOTE: I would use the form "(map :regexp-p)", or at least + ;; "(map (:regexp-p regexp))" but they require map versions from + ;; ELPA. That would be fine, except that I can't automatically + ;; install those versions with makem.sh into a sandbox, because + ;; `package-install' doesn't accept a version argument. So I + ;; have to use `plist-get' here for now. Maybe when we drop + ;; support for Emacs <28... + (`(link ,(and description-or-target + (guard (not (keywordp description-or-target))))) + (setq org-ql-preamble + (org-ql--link-regexp :description-or-target + (regexp-quote description-or-target))) + nil) + (`(link . ,plist) + (setq org-ql-preamble + (org-ql--link-regexp + :description + (when (plist-get plist :description) + (regexp-quote (plist-get plist :description))) + :target (when (plist-get plist :target) + (regexp-quote (plist-get plist :target))))) + nil) + ;; Planning lines. (`(planning . ,_) (setq org-ql-preamble org-ql-planning-regexp) @@ -838,6 +891,47 @@ replace the clause with a preamble." (query (-flatten-n 1 query)))) (list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold)))))) +(cl-defun org-ql--link-regexp (&key description-or-target description target) + "Return a regexp matching Org links according to arguments. +Each argument is treated as a regexp (so non-regexp strings +should be quoted before being passed to this function). If +DESCRIPTION-OR-TARGET, match it in either description or target. +If DESCRIPTION, match it in the description. If TARGET, match it +in the target. If both DESCRIPTION and TARGET, match both, +respectively." + (cl-labels + ((no-desc + (match) (rx-to-string `(seq (or bol (1+ blank)) + "[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]"))) + "]]"))) + (match-both + (description target) + (rx-to-string `(seq (or bol (1+ blank)) + "[[" (0+ (not (any "]"))) (regexp ,target) (0+ (not (any "]"))) + "][" (0+ (not (any "]"))) (regexp ,description) (0+ (not (any "]"))) + "]]"))) + ;; Note that these actually allow empty descriptions + ;; or targets, depending on what they are matching. + (match-desc + (match) (rx-to-string `(seq (or bol (1+ blank)) + "[[" (0+ (not (any "]"))) + "][" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]"))) + "]]"))) + (match-target + (match) (rx-to-string `(seq (or bol (1+ blank)) + "[[" (0+ (not (any "]"))) (regexp ,match) (0+ (not (any "]"))) + "][" (0+ (not (any "]"))) + "]]")))) + (cond (description-or-target + (rx-to-string `(or (regexp ,(no-desc description-or-target)) + (regexp ,(match-desc description-or-target)) + (regexp ,(match-target description-or-target))))) + ((and description target) + (match-both description target)) + (description (match-desc description)) + (target (rx-to-string `(or (regexp ,(no-desc target)) + (regexp ,(match-target target)))))))) + (defun org-ql--format-src-block-regexp (&optional lang) "Return regexp equivalent to `org-babel-src-block-regexp' with LANG filled in." ;; I couldn't find a way to match block contents without the regexp @@ -1073,6 +1167,51 @@ COMPARATOR may be `<', `<=', `>', or `>='." ((pred symbolp) ;; Compare with function (funcall level-or-comparator outline-level level))))) +(org-ql--defpred link (&rest args) + ;; User-facing argument form: (&optional description-or-target &key description target regexp-p). + "Return non-nil if current heading contains a link matching arguments. +DESCRIPTION-OR-TARGET is matched against the link's description +and target. Alternatively, one or both of DESCRIPTION and TARGET +may be matched separately. Without arguments, return non-nil if +any link is found." + ;; NOTE: It would be preferable to avoid this manual argument parsing every time the predicate + ;; is called, but pre-processing it to a normal form gets complicated with the preamble and + ;; pre-processing, because we don't want to display a query like "(link :description-or-target + ;; "FOO")" in the view header, which would be ugly. So, since preambles are expected to be + ;; enabled nearly all of the time, in which case this function won't be called anyway, it's + ;; probably not worth rewriting code all over the place to fix this. + (let* (plist description-or-target description target regexp-p) + (if (not (keywordp (car args))) + (setf description-or-target (car args) + plist (cdr args)) + (setf plist args)) + (setf description (plist-get plist :description) + target (plist-get plist :description) + regexp-p (plist-get plist :regexp-p)) + (unless regexp-p + ;; NOTE: It would also be preferable to avoid regexp-quoting every time this predicate + ;; is called. Ideally that would be handled in the query pre-processing step. However, + ;; handling that properly, in combination with preparing the query preamble and whether + ;; REGEXP-P is enabled, is also complicated, so let's not. + (when description-or-target + (setf description-or-target (regexp-quote description-or-target))) + (when description + (setf description (regexp-quote description))) + (when target + (setf target (regexp-quote target)))) + (when (re-search-forward org-ql-link-regexp (org-entry-end-position) t) + (pcase description-or-target + ('nil (and (or (null target) + (string-match-p target (match-string 1))) + (or (null description) + (string-match-p description (match-string org-ql-link-description-group))))) + (_ (if (and description target) + (and (string-match-p target (match-string 1)) + (string-match-p description (match-string org-ql-link-description-group))) + (or (string-match-p description-or-target (match-string 1)) + (string-match-p description-or-target + (match-string org-ql-link-description-group))))))))) + (org-ql--defpred priority (&rest args) "Return non-nil if current heading has a certain priority. ARGS may be either a list of one or more priority letters as diff --git a/org-ql.info b/org-ql.info index d20b262..10b5e6e 100644 --- a/org-ql.info +++ b/org-ql.info @@ -381,6 +381,12 @@ Arguments are listed next to predicate names, where applicable. Matches if heading level is equal to or between NUMBERs. ‘(level COMPARATOR NUMBER)’: Matches if heading level compares to ‘NUMBER’ with ‘COMPARATOR’. ‘COMPARATOR’ may be ‘<’, ‘<=’, ‘>’, or ‘>=’. +‘link (&optional description-or-target &key description target regexp-p)’ + Return non-nil if current heading contains a link matching + arguments. ‘DESCRIPTION-OR-TARGET’ is matched against the link’s + description and target. Alternatively, one or both of + ‘DESCRIPTION’ and ‘TARGET’ may be matched separately. Without + arguments, return non-nil if any link is found. ‘outline-path (&rest strings)’ Return non-nil if current node’s outline path matches all of ‘STRINGS’. Each string may appear as a substring in any part of @@ -732,6 +738,8 @@ File: README.info, Node: 05-pre, Next: 041, Up: Changelog *Added* • View dispatcher using transient.el (like Magit), bound to v in search/view buffers. + • Predicate link, which matches descriptions and targets in Org + links. *Changed* • Binding to refresh search/view buffers changed to r. @@ -1105,27 +1113,27 @@ Node: org-ql-sparse-tree7044 Node: Queries7844 Node: Non-sexp query syntax8752 Node: General predicates10459 -Node: Ancestor/descendant predicates15266 -Node: Date/time predicates16394 -Node: Functions / Macros19049 -Node: Agenda-like views19282 -Node: Listing / acting-on results20687 -Node: Changelog25289 -Node: 05-pre25853 -Node: 04126121 -Node: 0426363 -Node: 03230294 -Node: 03130671 -Node: 0330866 -Node: 02333839 -Node: 02234065 -Node: 02134331 -Node: 0234528 -Node: 0138563 -Node: Notes38664 -Node: Comparison with Org Agenda searches38826 -Node: org-sidebar39698 -Node: License39977 +Node: Ancestor/descendant predicates15674 +Node: Date/time predicates16802 +Node: Functions / Macros19457 +Node: Agenda-like views19690 +Node: Listing / acting-on results21095 +Node: Changelog25697 +Node: 05-pre26261 +Node: 04126610 +Node: 0426852 +Node: 03230783 +Node: 03131160 +Node: 0331355 +Node: 02334328 +Node: 02234554 +Node: 02134820 +Node: 0235017 +Node: 0139052 +Node: Notes39153 +Node: Comparison with Org Agenda searches39315 +Node: org-sidebar40187 +Node: License40466  End Tag Table diff --git a/tests/data.org b/tests/data.org index 1f618ca..b7a13cb 100644 --- a/tests/data.org +++ b/tests/data.org @@ -91,6 +91,8 @@ Gotta buy one first, though. ** CHECK /r/emacs :website:Emacs: DEADLINE: <2017-07-05 Wed +1w> ++ [[http://reddit.com/r/emacs][Link to /r/emacs]] + ** TODO Shop for groceries :food:shopping:@town: SCHEDULED: <2017-07-05 Wed +1w> :PROPERTIES: diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index bf2340f..605d32a 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -217,6 +217,7 @@ RESULTS should be a list of strings as returned by :to-equal org-ql-test-num-headings))) (describe "Query pre-processing" + (it "level:" (expect (org-ql--pre-process-query '(level "1")) :to-equal '(level 1)) @@ -225,6 +226,19 @@ RESULTS should be a list of strings as returned by (expect (org-ql--pre-process-query '(level ">" "1")) :to-equal '(level > 1))) + (describe "(link)" + (it "with one argument" + (expect (org-ql--pre-process-query '(link "DESC-OR-TARGET")) + :to-equal '(link "DESC-OR-TARGET"))) + (it "with one argument and :regexp-p" + (expect (org-ql--pre-process-query '(link "DESC-OR-TARGET" :regexp-p t)) + :to-equal '(link "DESC-OR-TARGET" :regexp-p t))) + (it "with keyword arguments" + (expect (org-ql--pre-process-query '(link :description "DESCRIPTION" :target "TARGET" + :regexp-p t)) + :to-equal '(link :description "DESCRIPTION" :target "TARGET" + :regexp-p t)))) + (expect (org-ql--pre-process-query '(and "string1" "string2")) :to-equal '(and (regexp "string1") (regexp "string2"))) (expect (org-ql--pre-process-query '(or "string1" "string2")) @@ -575,6 +589,23 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((heading "Take over" "world")) '("Take over the world")))) + (describe "(link)" + (org-ql-it "without arguments" + (org-ql-expect ((link)) + '("/r/emacs"))) + (org-ql-it "with description-or-target" + (org-ql-expect ((link "emacs")) + '("/r/emacs"))) + (org-ql-it "with :description" + (org-ql-expect ((link :description "emacs")) + '("/r/emacs"))) + (org-ql-it "with :target" + (org-ql-expect ((link :target "reddit.com")) + '("/r/emacs"))) + (org-ql-it "with :description and :target" + (org-ql-expect ((link :description "emacs" :target "reddit.com")) + '("/r/emacs")))) + (describe "(outline-path)" (org-ql-it "with one argument" (org-ql-expect ((outline-path "symphony")) From 9b2ff276a0419715a02cb36127e450756afcfebc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 24 Feb 2020 01:48:09 -0600 Subject: [PATCH 111/560] Tests: Tidy --- tests/test-org-ql.el | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 605d32a..8085686 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -218,13 +218,16 @@ RESULTS should be a list of strings as returned by (describe "Query pre-processing" - (it "level:" - (expect (org-ql--pre-process-query '(level "1")) - :to-equal '(level 1)) - (expect (org-ql--pre-process-query '(level "1" "2")) - :to-equal '(level 1 2)) - (expect (org-ql--pre-process-query '(level ">" "1")) - :to-equal '(level > 1))) + (describe "(level)" + (it "with one level" + (expect (org-ql--pre-process-query '(level "1")) + :to-equal '(level 1))) + (it "with two levels" + (expect (org-ql--pre-process-query '(level "1" "2")) + :to-equal '(level 1 2))) + (it "with a comparator and a level" + (expect (org-ql--pre-process-query '(level ">" "1")) + :to-equal '(level > 1)))) (describe "(link)" (it "with one argument" From 4b1e253ee910a177733c0230ffe63e9ab1cd3798 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 26 Feb 2020 19:11:40 -0600 Subject: [PATCH 112/560] Fix: (org-ql-view--add-todo-face) Always return to-do keyword Even when org-done-keywords-for-agenda is nil. I'm not sure when this was broken, but the logic was wrong in this function, and this is the intended behavior, so this is a bug fix. Released as 0.4.2. --- README.org | 5 +++ org-ql-view.el | 10 +++-- org-ql.el | 2 +- org-ql.info | 106 +++++++++++++++++++++++++++---------------------- 4 files changed, 71 insertions(+), 52 deletions(-) diff --git a/README.org b/README.org index e7c43e2..180138f 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.2 + +*Fixed* ++ Items' to-do keywords were not shown in views. + ** 0.4.1 *Fixed* diff --git a/org-ql-view.el b/org-ql-view.el index f141270..1a132d7 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -666,10 +666,12 @@ property." element)) (defun org-ql-view--add-todo-face (keyword) - "Return KEYWORD with TODO face added." - (when-let* ((org-done-keywords org-done-keywords-for-agenda) - (face (org-get-todo-face keyword))) - (org-add-props keyword nil 'face face))) + "Return KEYWORD with Org to-do face added." + (let* ((org-done-keywords org-done-keywords-for-agenda) + (face (org-get-todo-face keyword))) + (when face + (add-text-properties 0 (length keyword) (list 'face face) keyword)) + keyword)) ;;;; Footer diff --git a/org-ql.el b/org-ql.el index 6008e8b..65f1053 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.1 +;; Version: 0.4.2 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index 1a6a498..a64db08 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.2: 042. * 0.4.1: 041. * 0.4: 04. * 0.3.2: 032. @@ -704,6 +705,7 @@ releases. * Menu: +* 0.4.2: 042. * 0.4.1: 041. * 0.4: 04. * 0.3.2: 032. @@ -716,9 +718,18 @@ releases. * 0.1: 01.  -File: README.info, Node: 041, Next: 04, Up: Changelog +File: README.info, Node: 042, Next: 041, Up: Changelog -5.1 0.4.1 +5.1 0.4.2 +========= + +*Fixed* + • Items’ to-do keywords were not shown in views. + + +File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog + +5.2 0.4.1 ========= *Fixed* @@ -728,7 +739,7 @@ File: README.info, Node: 041, Next: 04, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.2 0.4 +5.3 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -809,7 +820,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.3 0.3.2 +5.4 0.3.2 ========= *Fixed* @@ -822,7 +833,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.4 0.3.1 +5.5 0.3.1 ========= *Fixed* @@ -832,7 +843,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.5 0.3 +5.6 0.3 ======= *Added* @@ -897,7 +908,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.6 0.2.3 +5.7 0.2.3 ========= *Fixed* @@ -907,7 +918,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.7 0.2.2 +5.8 0.2.2 ========= *Fixed* @@ -918,7 +929,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.8 0.2.1 +5.9 0.2.1 ========= *Fixed* @@ -928,8 +939,8 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.9 0.2 -======= +5.10 0.2 +======== *Added* • Function ‘org-ql-query’, like ‘org-ql-select’ but with arguments @@ -1011,7 +1022,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.10 0.1 +5.11 0.1 ======== First tagged release. @@ -1072,41 +1083,42 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1417 -Node: Screenshots1591 -Node: Installation1709 -Node: Quelpa2347 -Node: Usage2790 -Node: Commands3139 -Node: org-ql-search3612 -Node: helm-org-ql5260 -Node: org-ql-view5672 -Node: org-ql-view-sidebar5870 -Node: org-ql-view-recent-items6226 -Node: org-ql-sparse-tree6710 -Node: Queries7510 -Node: Non-sexp query syntax8418 -Node: General predicates10125 -Node: Ancestor/descendant predicates14932 -Node: Date/time predicates16060 -Node: Functions / Macros18715 -Node: Agenda-like views18948 -Node: Listing / acting-on results20353 -Node: Changelog24955 -Node: 04125499 -Node: 0425726 -Node: 03229657 -Node: 03130034 -Node: 0330229 -Node: 02333202 -Node: 02233428 -Node: 02133694 -Node: 0233891 -Node: 0137924 -Node: Notes38025 -Node: Comparison with Org Agenda searches38187 -Node: org-sidebar39058 -Node: License39337 +Node: Contents1432 +Node: Screenshots1606 +Node: Installation1724 +Node: Quelpa2362 +Node: Usage2805 +Node: Commands3154 +Node: org-ql-search3627 +Node: helm-org-ql5275 +Node: org-ql-view5687 +Node: org-ql-view-sidebar5885 +Node: org-ql-view-recent-items6241 +Node: org-ql-sparse-tree6725 +Node: Queries7525 +Node: Non-sexp query syntax8433 +Node: General predicates10140 +Node: Ancestor/descendant predicates14947 +Node: Date/time predicates16075 +Node: Functions / Macros18730 +Node: Agenda-like views18963 +Node: Listing / acting-on results20368 +Node: Changelog24970 +Node: 04225529 +Node: 04125676 +Node: 0425915 +Node: 03229846 +Node: 03130223 +Node: 0330418 +Node: 02333391 +Node: 02233617 +Node: 02133883 +Node: 0234080 +Node: 0138115 +Node: Notes38216 +Node: Comparison with Org Agenda searches38378 +Node: org-sidebar39249 +Node: License39528  End Tag Table From a459204e7868a656fa106e288c099fb410ab4742 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 26 Feb 2020 19:57:16 -0600 Subject: [PATCH 113/560] Change: (view--complete-sort) Separate with spaces, not comma --- org-ql-view.el | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 5244508..1d7393d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -850,16 +850,21 @@ property." (defun org-ql-view--complete-sort () "Return value for `org-ql-view-sort' using completion." - (let ((input (->> (completing-read-multiple "Sort by: " - (list "buffer-order" - "date" - "deadline" - "priority" - "scheduled" - "todo") - nil nil (when org-ql-view-sort - (prin1-to-string org-ql-view-sort))) - (--remove (equal "buffer-order" it))))) + ;; Use space to separate sorting predicates, not comma. + (let* ((crm-separator (rx space)) + (crm-local-completion-map (let ((map (copy-keymap crm-local-completion-map))) + (define-key map (kbd "SPC") nil) + map)) + (input (->> (completing-read-multiple "Sort by: " + (list "buffer-order" + "date" + "deadline" + "priority" + "scheduled" + "todo") + nil nil (when org-ql-view-sort + (prin1-to-string org-ql-view-sort))) + (--remove (equal "buffer-order" it))))) (pcase input ('nil nil) ((and (pred listp) sort) From fc91bdd4836a026ae5b5df18ed133f85cf3ff138 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 27 Feb 2020 19:57:42 -0600 Subject: [PATCH 114/560] Add/Change: (org-ql-view--contract-buffers-files), etc. When offering completion of org-ql-view-buffers-files, and when formatting it in the header line, use the "contracted" form when possible (i.e. show "org-agenda-files" instead of a list of all the expanded agenda file filenames). Fixes #95. Thanks to Kilian Sprotte (@kisp) for suggesting. --- org-ql-view.el | 67 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 1d7393d..ae1a5f0 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -444,7 +444,7 @@ If TITLE, prepend it to the header." (length "In: ") (length "Query: ") query-width 4))) - (buffers-files-formatted (format "%S" buffers-files)) + (buffers-files-formatted (format "%s" (org-ql-view--contract-buffers-files buffers-files))) (buffers-files-formatted (propertize (->> buffers-files-formatted (org-ql-view--font-lock-string 'emacs-lisp-mode) (s-truncate available-width)) @@ -594,7 +594,8 @@ dates in the past, and negative for dates in the future." :variable 'org-ql-view-buffers-files :prompt "Buffers/files: " :reader (lambda (_prompt _initial-input _history) - ;; FIXME: Figure out how to integrate initial-input and history. + ;; This doesn't use the Transient `initial-input' + ;; argument, but it gives the same result. (org-ql-view--complete-buffers-files))) (define-infix-command org-ql-view--transient-super-groups () @@ -811,25 +812,53 @@ property." ;;;;; Completion +(defun org-ql-view--contract-buffers-files (buffers-files) + "Return BUFFERS-FILES in its \"contracted\" form. +The contracted form is \"org-agenda-files\" if BUFFERS-FILES +matches the value of `org-agenda-files' (either the function or +the variable), \"org-directory\" if it matches the value of +`org-ql-search-directories-files', or \"buffer\" if it is the +current buffer. Otherwise BUFFERS-FILES is returned unchanged." + ;; Used in `org-ql-view--complete-buffers-files' and + ;; `org-ql-view--header-line-format'. + (cl-labels ((expand-files + (list) (--map (cl-typecase it + (string (expand-file-name it)) + (otherwise it)) + list))) + (pcase (expand-files buffers-files) + ((or (pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) + (pred (seq-set-equal-p (mapcar #'expand-file-name org-agenda-files)))) + "org-agenda-files") + ((pred (seq-set-equal-p (org-ql-search-directories-files))) + "org-directory") + ((pred (equal (current-buffer))) + "buffer") + (_ (let ((print-length nil)) + (concat "'" (prin1-to-string buffers-files))))))) + (defun org-ql-view--complete-buffers-files () "Return value for `org-ql-view-buffers-files' using completion." - (if (and org-ql-view-buffers-files - (bufferp org-ql-view-buffers-files)) - ;; Buffers can't be input by name, so if the default value is a buffer, just use it. - ;; TODO: Find a way to fix this. - org-ql-view-buffers-files - (pcase-exhaustive (completing-read "Buffers/Files: " - (list 'buffer 'agenda 'directory 'all) - nil nil (when org-ql-view-buffers-files - (let ((print-length nil)) - (prin1-to-string (cons 'list org-ql-view-buffers-files))))) - ((or "" "buffer") (current-buffer)) - ("agenda" (org-agenda-files)) - ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) - (buffer-list))) - ("directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) - (else (s-split (rx (1+ space)) else))))) + (cl-labels ((initial-input + () (when org-ql-view-buffers-files + (org-ql-view--contract-buffers-files + org-ql-view-buffers-files)))) + (if (and org-ql-view-buffers-files + (bufferp org-ql-view-buffers-files)) + ;; Buffers can't be input by name, so if the default value is a buffer, just use it. + ;; TODO: Find a way to fix this. + org-ql-view-buffers-files + (pcase-exhaustive + (completing-read "Buffers/Files: " + (list 'buffer 'org-agenda-files 'org-directory 'all) + nil nil (initial-input)) + ((or "" "buffer") (current-buffer)) + ("org-agenda-files" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("org-directory" (org-ql-search-directories-files)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else)))))) (defun org-ql-view--complete-super-groups () "Return value for `org-ql-view-super-groups' using completion." From e811ac5680078ee5aacb05601e4ce3b1c15ca33d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 1 Mar 2020 08:54:32 -0600 Subject: [PATCH 115/560] Docs: Add mascot --- README.org | 4 +++- images/dog.png | Bin 0 -> 11465 bytes org-ql.info | 31 ++++++++++++++++--------------- 3 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 images/dog.png diff --git a/README.org b/README.org index 9dcc787..63ca963 100644 --- a/README.org +++ b/README.org @@ -1,7 +1,8 @@ #+TITLE: org-ql # NOTE: Using =BEGIN_HTML= for this causes TeX/info export to fail, but this HTML block works. -#+HTML: +# #+HTML: +#+HTML: # NOTE: To avoid having this in the info manual, we use HTML rather than Org syntax; it still appears with the GitHub renderer. #+HTML: @@ -406,6 +407,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Added* + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. + Predicate =link=, which matches descriptions and targets in Org links. ++ Mascot. *Changed* + Binding to refresh search/view buffers changed to =r=. diff --git a/images/dog.png b/images/dog.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c81ed0f6ef843eb2782b71e14e9e22c379aae6 GIT binary patch literal 11465 zcmeAS@N?(olHy`uVBq!ia0y~yVANq?U|7e&!oa|wR{dip0|Nt7lDE4HgXhxTTWkyr z44efXk;M!Q+`=Ht$S`Y;1Oo#Ddx@v7EBg~>Mm|d+&wcil3=BF^o-U3d6}R5bEl&_R zdi%KjbZ`E>%?rC4LY8WZEz#5n6Jc=)e6v@vOJrl?o~|TTk!t3Rfvg{wH)yzqtP;^| z^2%3SqHg|P-rRhqZu$0|Dkoy!?XFkZzJ2><>)&tA82kUU({pN_&5{)`Q*VyDG~cG4 zV_T9K?|eV4UwExZ`IP~18rVRyYYyTxRe-19R3RHs(#OVbhkJMX=^ z-U5YR0;lwnIu}b7>nuJOyTj-PTp4ym|1b|k&#;QnX)@k!m;YpT&J+V zOR`!WdE8NYb?s$Tr(t4iPG<8Gf$qzac`m~Jw=I7a&IvlC(qm&F|S zxc6LJ?Xz+FNyXcZrCL*6+9n@!^G&_4eEw!LmkQ&B&O(m7<&ya~=PXU!@>^N>;~qb~ zoqb`&$KI+j-1(Doafppe;mDOt z_@UNb#Bit2p+Ihe2RqB=%AUt{t`&w)7xyb|+HmTbVZVXQ#}1Kge9IR1-R!Y#`g(*} zZ{Eb?K553)f`24ZqV68oz1S}3`Qyxoip`b%;xjyj7f4Amn54)z&Hu}>uyS|!tz%-d zzwJL~?pXg@xpWb~O3;TLo;pblRuwDyW?ys24--CKJ;%T1Lg}LR#7}Fib*_D9a_??t zlIygabizS8*XeUX*PUq3+W*!~qCAf{tyo1mbNW6`_~Ywdq3!b_E$^Ud0d7mH2`@R*#GcRc0 z_UHYn4GSjU2$K55x=~^A+Fv(TeQn%6SLMN@a8uQ~T;bVLt}_xReQQ`K*L3&_v)-c# z%oBf1H(uc@^B~Rg^3G-}9oe zmbOz{6Vh2G&-BZ7S9*DOpXx<{)Qw)jPw$5?iMvKDYBf{c+vKo8I>T!k^T7;nt@P8M zO_HT8ZH`OtdEl{PTG7lh(XT7`r=)Y;H)^^s!13)9lj$OUjhKmN_|7idH~nso8l!lw z49iE&i9;DHQ{v= z$ML`iF)XheL@ZBn6v^ILYiAUDm@QbL*N~@bc9Eg0VAzbb0xt1K*AyO2WbB!C`PKoY zB~dvBTkd&xU;P!=Rb?G^VY2_0iSMJ?F5CQCafo}m^rJOFSN@eZbDS_+usmqn-1RK! z(oy;$H~0e`rQHv@^5kB9bf~%gzJx>Q*IE&E%ULr;iuBi&B}{Bu?QGC)mzZ&P^~2oM z74rEDXZw39cSpYZUVZbB&bz*KQvP)>8V}b8Fm|L*Wahu`yQEzq;w(?@{x#vHb2g&diRHR#4aI`pVicJU3ZWC6Ec>ITJLLQT0T@j9T{7&c+YZjl5VbRAL8zZtl@_%5cf4IcCU4LXxf zBpB&`-hSV+c3ID!>mOC(i)Qc`oiOdal9%M6(#ayU!pB%@;wiI79trZc9uF0CGmjADXR&7~k*Lfw;OtQwCZ(~KlL=Ux(PbPY4on3J> z@mFA@idk{P);9}nvTq(y?3kx;4&W_gYUVE?Rny@Wk)^2n>rC{B%y-`PMbF}p@ zgQ<)=rWO7<>tS|z7O#wwz5{n|MDA|;$vH+hPVoqxTxvIWg|Cd^4iAM+38AKE+)pRE z+gU!D>?>nTs|Y%?ppZ zUA$@OIS!WcRnvY?I4l@v9(%r$=Q(4P*hf99k76_X)@$sa@y2rL=D!E#Zs}0D*p;eL zKheK2O1(-$VScjAqYX9b+!_TE$MfzcHTtOpc-F;v7RMZr;+wu;(c48bi%+Vy*Xv%N z>FE9|>vY5Zmxp$iELmTokQ&ry_{6A3{6|Y%j{c#$sYQb3pBXEo{)?vHKJ4&FIi2y* zBD=FMj^_3xaa_MJPfA6IJ7j@OZ-&45xh2+%BTxNPD!szaVB=x=ze9)uv zAkH1vzH}UC+PLgTxA+R4Bd0aC^p-qG+IG38F-I}H`ya=)RPDQK1!F4~xEx#ex8}&o z)Iz}m?r2#b^W%|+XD^%ZSl-7l-hScoqKZIe2KEKP)zw{&CTa`@=ZkuacQjnnTC`ZY z_okn@n`mZA-GwWkZV1hms(z#}ru40>K zu6-$T@5Qz9zgxbmH2s#1yKQu~@ZD4OGh9+HK6AV;Zu!Kwb*V3h%@czQOE%Z#S?Tq@ zx0t-ygH@|Q>TJfL+?qh9#kaQaIcqa-F*oPLbm`R@pRDT~m^Mt1{Bw$lW#^MkjXt8f zuO9IoZoYk5F{r_f;mV}y`AhfaruU|1HFO$zN~=D;TJ_y{fqBzjwfw{7X0H!Fk2p5_ z&ZC4?=UqS8SF&xk{UE1$sIp>*Y{U1D3K8DAKc#l6Ja#>qWBKPq@)fnlA09;)_Gj%l z`Tt_0y5O2chRKn~Bv__PXDHpCDfHt#`!?^^(sfT71zfkh4M~`)`6+vX&F_*DzC(xB z@|#C~dwcY(w@-lJx_{gDg*?dPS~4+t`qQka4a^6#uRLUWY1}c9(Y>-pRryTM$qLoY zON*!ES5B5ziH^LHyhw9ew&Y@8cb})$ho5hIb4kPf(as)ghJ1k}yWkVLO8zy~m8`i_ z+{!lFRLkBn=5=IC<_X_9TgoASnbEZUSMOCin9A`Q#Z?;KdvN@VZ|mg>Ch-+MpPhWd z(jz>i7nn&d&618j9OGuxwR=a)vMXHYW0*cKuIR0}ESS0FD67|7p9lV>U+jC5*3MC4 zX?_w?)UvN{YkSD2n@3!|j<42OzLH67qCa2L(;X5=;%B*L3r;xUaA(Pf)}Xcg9|8hc z_n9*EPKhjQ*wxonAyB9G=G!gFJ?GZ$_KKKdbmNWreB-(GGaj~Y`myAggmcSu^Mq$H zZ-48(VK|rAWh8s$(S~0~-9D{kJ799@3A6Q~Vx59J|18@c%#84@J->iC^3SQaArE7j zuOFGcW5&U%q?K6-Li9H&O8RaWV0rltc$a(EBapMB-vYfy}y01ByVcpHiLu3uiC0VY?RUew#vs* z{HkgH(g(4VUgo}7roMFBl%;E*_Z9nggcmPYjQa1+!n$S~=c|`zYA&rf!p?V+Y1>7X z0|#m<_MTLqy{fiOjK8V<>T~~-s=+fIqFYr0R#$XPI~7pOxL9CM?uQFpl0GjlZMm>| z<|+G>$=-TR%x@lRIKT8~J~h!n=iTJ1&*m@sv~sg${Iky-e8rp3ZoIGjquFy7=Yhjj zGlM?1MX?8i!%=IR$GL+6}zk}FS1vse%}rTyx@c;Bm|wqOUGLaQVd~mBmyn`+UX!_nT#Q zUcVB%`)0p;@y8>Rc8rN= z@>E{>H>1?L=@+9;p4*(R+2XRd*RZ^NHJ$UyGI3U!H2IlJj9X=Vv$YlGUp?ctq1!j+ z?0237whQ-DuGD({eWVm@|8&wZ!)F^hr}`wTb^mPnnWNt8V`O>iyx8)Xm5E!*BL8Nr zytBV{YqDSR#NMVqdQPVs_x0`y2~+daes$wU);~vu9jpZ(w>(Vz^5AX5%>L|%V>#@T zAG$QZV3G3u8$IdT#FcXH#eR%IE0x#V{+Ol~zGe2!!y%spD{^YMe&0C7wJ)91`(_fC z*eUh7^)HYAwK;85s`}KjdzuQf=+5(v_7U;X^A+~2H;tbB?$z7OXsmZB8p6PrS{wtt$GdOwe4rw-Gkt{qe2PZx&W)cF4Ftq;SyWc{X^C{Wo3Yfl$y2M^oR%_2*-KiZ-PE zeR+g4j8|9eZ}kIj(aG-)f892HNB7M?2e!^qT;Jcywm{(ehwjw-OV2FS3pmf{+qw6f z&>N2R@}Jc%{}mB!y|$#fe*KrF{?Fpm z^4>5tNTS-PgXK=qual2#R&qYM&=#RE+3!_N=*epp{&V+CU+AxG|NH8eYeMcymK?_l z&Axiwc(r+R%~3 zqw-@^=%$JP79CsnFXU;gjm|}uuc<7>-4}ixQnFcM$rgC)l{>S@8ivZL3y}{YuY2N(9e55-{zP`u+_w_eUHz$Tc)1K2zcFd{4dwS z_j@b4Ql=?sEYL1kxW%CU%mbypt*<@GL)aV(S{5%`q*He5dh{GOZkFQ~PIo6%9f=Rr zZs>Deci`^<&e^qoMmr?d*iKv86WElz_lhD1i}BSJTLap7{`0L#bK)=;Kc2s4d5wqH zp5tFM=l3q9}p)@4fmtm_e&yF~HEUa~HXnA-yT`wL>)O4i^Xl0yeZOjHe$%gMv%sDw3s&7^y>vR`sN@sH zAENnh+(mC0J92A(+HM9bTc`=i7hI z`lWocx|;aXD{8$MW8-GE*e?l9CvQz%Jjwl(#wzXng_Xa3E-QaJ!Q7UiGSQlM-tNvm z`CGDk^f%X?;aBJMNc9$EeO;^P64AqYa@vQT{T{_LqC+?jx~#e|qxj0cqa6&(t~+w@ zNpYC4R<2_3oq1GZKmXhEsTC7W*D+LOo|_hUYvO*(td-Nc*1mZAeMXn7*8QKdA02$} znDDN+yd&k^0%Nz3?WswBg%5J=PdxWECwx`?qO_8BYEL=+vCt}^NrnXyTE?GCPkYbN}99(42GT(kREm$Rqe%34*s zxasPpDVOfKc&C2yHvaHiBH;Ami#prs5$sUpy~zl&8+Iv=CXo4rZ+a%+`h0P;pnHeCtI1$&OBc>b=MaY zr=9taRM-=^i%irDYXn8Uv*h+(oqF_%@`?2QUYVuG>Qk?+o+Ps)Pwq=H3twJtwD#Qi zusN*>g4{ac7WP^Z1#K&X^QJDlsLWyYKsS4Xcl2S-PZ^GSFW-b+J??batGDQ^c=pdZ z$`^N?TK`c=;MNBHC7K)el{n^aF-)1`%Q$)J?0p5@om^sfa%ZpNbB{QY(stTPEcD5} zR*qL2yT592tc&qjyUR4`xYL~%9vkAe^=N6{Ibp@pKO?L|bcI{>)L8Hakht+0kwMK8Sne`&iBr~dYY982=cm1-OGR~}U~`?%}UX{Up(mr|qe z8!@qnui4JKKl6;(S~IuY+@_e*j79=7p+8Sl&murN(#QQGY@x9Yx#KdfU(gwh1h?4-FsP$XD+tf*xe_w zGh+kWi@i@8@>dy5*wy}W_u97Nsn3-jWgfI}wl4kIept$}WAf^|i`IIcU3{%oMB-Fy zl`+?%)VL=eiM0)XJwkq3J?mU1`FHEyg)FT8&J)t2ZtFheJ2%DA=HJPUv)MNsiG5Sh z;-@@$W1s8``6wZ=FTWg4K2i8_#=&EgUX=6g_T@Pmhmtb0J~h7#Td_6DsrkIo-J^+a zv%57p`XukYzWlW7{nrN0nWuHSs@*3=I)++rb=T)K=QM_-b@h<{q22gt-SN z-M>HSXN|@YRbQ4vxszXg(Jt&UTX}i=>i9Wb?276qWp$L;Zak|A73N4!;V#E@-gizsceM`Cog|NhOPW2C4j^Ph(lMd6OqiJ-yH=WJ!%g!t1`i%O@`F zi7sDSxu^ZYvQAqgr9X`AZ_m1Y*kP9T)}g@VmH+9#9ifHU9WPBbpFa`)?9_r|Z2ec( zr4FZLO%m{Kl{3;A)&cb=WP2g z89>daynU)ESv-wtDnDn&ti5`2Usu;8!G98K(u}Sqo!2yB=dxR% zd{1Cn{Y<^1pCj4d_D-KN#cpq|Y?DqFlXgUFf{k(|M}r!NoLSGxoiS;_Cm;FmfArOK zy2kwF>$=Yx&1l>F_sQQQA4Qw4Zp*3M9=W3Bnv3hnH9^14eZQsHd}jI}`A2Q?2XltI zC!bq1ck(7R_f5B%AGwL)bSg(thA9T`Q)?ecELF(zXypa{Ai7s;M!jEZ?|;!f>rCMx$-nApDa|Bab)|+5%<*ma&3;; zhnsUwdfgQMw|wWVDBDFn0yF0*OHJL9S8jaa+UGLv*p;srY-sO3bnA3EV}ZTgG;iK# z%*Xrd<;BGw@~yHw@nhq)4_<~5TceahLf1(+*Zf_}_-Hn|p8H5Ssrg-}*#wU-so6VhZhDYZTKiw|B+(+MMV)sU5PZ`k1uOH+ncfOqQ{Gv)xH2Dth&aQq?b6$*~6xB^tX#uiEqMxJaS>bwPHUMSrHs zyBe3RDN}1q==k%e=glR)Wsj2zW?SuKIzQX#zKuwRAgf-G%n#+y5vQ*xP2n(G?7LB? z(DKUSMSHC0Tiy3_OPsNO<)&#?A3I8R?=JM7)Fd3vq3ZMCa<>%2$xR&x&QDwN!>{JJ z)V~W!j8>Y?50gGs%o6`G$(uLxqp<9ZczK;~U9YAHEH?SFW`X$3b4JH5w_g63CXsfl zLLfh6&Qbw&=FVrABe-sETVVFbsO|2iXurv4SS5Ql_?YP{-#8!Td~nJh8zOAAUK==)BD{cAf?mbJ_J^R|R z$nr>;^w|#~y6d)OhHN-@)yn9qO4z;^+6S||8S?Y>p8C0cl>Gl#`CfYCTaT@?EqMyx z%;A(}{%f(A%YE8Mj^K{XfeZ`P4(Bpg)fldNKfxvS0n;*t8?Lgm3}SlU^YS#!Udr+2 zln&S1fM-P;&TBVT-#0i^nmRFe?YibQk8;^Abbh zWJbUF#BciVo_IrCrkN$r1FKcVX52r!v;}y=pT{RgF~>)4V?8~+e3Ohh=d6_(&2U*JqpP-hXxG-m3YBazX{}CV#H=6`LWH-g}#a zZ354khrVZ7ir0H?Nwa+Lxy!>OAb)#zwg5*O!%3;Xw>+M9XIEUhfA(}+yVM++b(^?^ za`J!IO2=_#MBR1L`Do*B`_|l3%i)Cb)c;|rfg8>RXYX&Dq_fekz_2OSCadGZE>)d( z$5+Vv@(E3Q5w`MIKAXj>w+vw$UT#Z`kTPmGzGZRS6x)NV7P(G8Y~Xrk;{+~;T;EXs z{uA$Zsa0P&qj0=GF#DDRr|47OsTaug%xVAqCGV$h)HDn;PTsb?a`F5v3wPV@ zym))kqWx#{KZ>kac5TAhrdcMljE?%hJzmm%`QGjz+0{?G@;7;I?@dsVh)7xU{_a%O zpk3dOB(2eXS+THTi;0V0>P<1@Z~g23WC=5F^R`Y8oth9dePveZOUDxu>x>#dwY~d! z?9*Qh*Srwxo_DX}q~G7yHj=Mi)5((%!g2D`S=EV?C!RXnEhTgLQ1-beyq;PLDqn+_ zZc>cspS`K@7h`lqSZ}QP>i1@?2Ui8e%Rjqm^ULbW1i|^OoWECQ`Dl6>?y9Kzuuk*m zx9n97S3dS->OboJbACcdb$H~7xpIlgzr3GomcIVF<Dm%AH3HPpOI3sE9V6;!$o3 zQ^^Q%G(P<5UKXp4&>kn*a>b^*Yg{+nUKX}cc&)d;MD?7f9AS|>63sg~C6=+|i^VEM zZb-XvOogH3N&X#08%na94OVY`^~zWW_(3mg{Z9%Na6^U~5j%_V73@&*sJFKn@hcv*V+#hJ(* zjVw#EkA9jYa;v%R&JvEJcJ_1UsqWsc`uWD12+PA;BXXG|Ctp;a?7D`hC70*U+o#TA zk9KbBOp9B7E@K&k#GU)|PV|`j@;Ee^1+Sb}cw|M=%=IlVAIN$e_bJXu;Q0P|=N0ut zotW*mDzT@#XXj+ktURu@zO;V%!`=GIfg7?WcOFRIT=!|0KllA*-dFA|Ow8FFt>@mk z_>$UtV+)R17tf?r?9_Wwb}KT&OH5+l{p4R}nx9x!OUtp`oO7(ZZqJX>C%eB*-1fe6 z!`}NU*B&c2OO>RrN?T>)!}=gJ>_hLez;haH^;aykcnxaO)n@O}|HPv0?Y-{)ljRWy z&d*_-lO=IAt>vxkaRVVotL2j4j(KkEW_})WQ(YRr{p@EjMSHV1!& zwXJdVX^6<@x0OuN()i#xp@>o4_}#I?j{EuMtcp4R^nlsY>}y;rr@pE?S^9j&ukxfP zoYU5qZ09!q{lPUR?}EjeiBtBs=O!)dKFGnxP+->JwmU?Yzlka6<+7r(ZEZKs9nFf0 zP2@OLc{yJ%uw}st9mu zq;(bAM-I1DbVapIT6}Y&d0eT{(J0ZNU;UG+-Pi@!E;bAGILum~!C#|N9U8V&|I0=z zO)pyx*?n9RZ++H(dA(};cK3M+wp#gX7j4-nvaa1~Rq{OkD4z#gHf(+PH1NR8OM2lq zi;kxYYikFKyubKgH`)1&#ra2@dnER#3NtOR@h{w-`*5L(v~ZSGH&4v-tB1e*bH7<- z-+prUtJd{Z-_|5;y%gBSdd>W8`DYGE4!drXjYXbLC;U5;&6^6fmZUU4+!1E>IAo3E z*7?HQvTD?t{Fc@3)A(Vhz&fpa^TKWn4#!J4<9GfR%V{;_Yb#d2H8QUU#)7wmk+KS;gmo0x4`W_LbP>~8C} zxv`1a-G$8USC-pkeb(48RbG=pEugV~iQ?8B6wG{MiRTt$GoE zT1rU6_<`f6oIbgOd+W|`x$#Z>VZ*EgewX+Dh})cZ=NMz2#==$S^FN!PG}2qmetag6 z1LKWpe0aapV_usDLB>GMB7gV5Kv#jkDod0r`}hJ9_QO_b-dqvZ|?6=7;$ z!kPBy&7ZIAyMfQ^(r@i0k6v{juhKd3UTTv|wCp^gYqcAW9g7W)Y~8v=`{A`dFSqM+ zyR>%bH}!Z3>%3p}jw`k11W&}1YaP>X_8i~Pz~|4=7yV6Fd+U*j7uB+-ZRa|1?u5|l zPs?r`b8)>|yz=lCiQ2j>U&1thYMEv+*Mr`vyj8UyyEriw+~`0MZyEJ4{iz$ zU#JzpxBmV*;R0jfE9J>vC+e0e&$eH&Y?a})BS*71yylCfRh*lmC%M>&Ctu&V>8f~R z`&XVc(fS!&lf$*9iXB(B5N}Y~w1Q!YVupyP^0e{=|D&Rlet)XJJx%i9D>j)$X7Zb_ zggi-*aQ9w%v{K=<&+*U3l@-QP${ij?Vb7lIS@W$VT##q~G|8e3_fI@xi%M9tQcFd? z=A{CA;s?8V{SS7ZNGy1$LhC3UTlv0+sTl$V+!l3Q-9X>3R?*o&RqP3(e2{>4>g;-uZsQK9%J$&;DBS6 z3)jcD&0Uc@nrgC3vL;M1QV7vIr!b$tQO!)W*sJ=WLE!HamHE3uip;dzQ+lFr&1p@av^?Z2{le#*c&lOkVbzQ7DS;(14$FQ| zI{Na-j7PcoW)lyzs_F&)nXb>E+0|H5Cn>n{v*bZWme(tfTbBg<=D#`Zhz{=-Me&2n zPZfpwxlYyLzV5d-^ktZFrrue;eKoT^`Z5Y0s?F1j@vxFBvRJj~du`iPMfD92-ie&N z_c&UT?~+9AIqv=E)*i1ZWsXj54-35V-F>O8woswu`%lJ^Zyvg?d#;m}DYp0^Lrm(1 z-P85<9C;T0ahlMphf!9s?H{V*cT3D@V$Ghi?Wwlum$(+LP#bO$``S&3sn@)o`h7FK z!nrzPmHu~k4x6AkwGpeM?AI`59b%G?3i93j#JsahW>Z}Y*R{z~_opjNT>gYb_XfAM@7?5=xa3f_N96H>Qx~Uh7ns8wGGWi^ zPKPy02hQlbYTtXBGhuDd_DH|V{gIM>veMZP^u$Fr1fG`s-7u%n`G-ti>2BRO-c20aH zo#VbvjOlW);Lqxp&-NW>jaj)#+gtnoix`%sdfqap^$X%p>%;{8Ieg~ped&XbtHtGvt}fS~DrYL%xWG7ED(lu4jiswAm=79idgboyQ#Gnu z#3#v-2u1y2Z9V`iYE^6)+l$Mtl~~|S9*6X%U>b+R(#O^rL#@WUozTJ zv#O(OPtW@I0fHUr`c3;zF(`UjE?eXh$mwYHcj}KjtKC+-ZtRv^WmOvH!W9Rw}0C(JBDx4LBV@Z3azxfrd&Fx&asQ}18e4`BZe-~bN#jB zT<88*`tl`dLE~8_@tB&0wNja!W!)k+r)H~6^iuv7+$y#txG(-kx5>51OWss2?f#^| zJ3r5668CG44gC)pq-GagF9`Hx`=NNjOzh!3Cy}L{og8W>|6h8#YR}?JukxRcoW(lN_+AxvYe|_jiA%WI{j_nIY&2=&=lcuS>s;g()|_zp-Bb>i{tJgcbY17Z zKYNW&=vtlJoG&ZqGc55q`%ZbMmHfekqv?zD_1$-CbuC(Gy!+%+4(^{boY`De+H*E} zr0dr@+wRo9wLeu#_eKZ%iX$sy{Ns&o9?sdv!gXW)%);)T|Lj@0#%_%(BYGGZ7#KWV L{an^LB{Ts5rslu1 literal 0 HcmV?d00001 diff --git a/org-ql.info b/org-ql.info index b3f8d26..6f5744c 100644 --- a/org-ql.info +++ b/org-ql.info @@ -742,6 +742,7 @@ File: README.info, Node: 05-pre, Next: 042, Up: Changelog search/view buffers. • Predicate link, which matches descriptions and targets in Org links. + • Mascot. *Changed* • Binding to refresh search/view buffers changed to r. @@ -1131,21 +1132,21 @@ Node: Agenda-like views19705 Node: Listing / acting-on results21110 Node: Changelog25712 Node: 05-pre26291 -Node: 04226640 -Node: 04126802 -Node: 0427041 -Node: 03230972 -Node: 03131349 -Node: 0331544 -Node: 02334517 -Node: 02234743 -Node: 02135009 -Node: 0235208 -Node: 0139243 -Node: Notes39344 -Node: Comparison with Org Agenda searches39506 -Node: org-sidebar40378 -Node: License40657 +Node: 04226655 +Node: 04126817 +Node: 0427056 +Node: 03230987 +Node: 03131364 +Node: 0331559 +Node: 02334532 +Node: 02234758 +Node: 02135024 +Node: 0235223 +Node: 0139258 +Node: Notes39359 +Node: Comparison with Org Agenda searches39521 +Node: org-sidebar40393 +Node: License40672  End Tag Table From 132173b36efbb52425c9764836171b1dc62b40ad Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Mar 2020 00:22:41 -0600 Subject: [PATCH 116/560] Fix: (org-ql-view) Require crm Fixes #98. Thanks to @bepolymathe for reporting. --- org-ql-view.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-view.el b/org-ql-view.el index ae1a5f0..b966d14 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -30,6 +30,7 @@ ;;;; Requirements (require 'cl-lib) +(require 'crm) (require 'map) (require 'org) (require 'org-element) From 20f3ce747ce46d73818fad08078dc7c7abf6ec88 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Mar 2020 00:23:35 -0600 Subject: [PATCH 117/560] Fix: (org-ql-view--contract-buffers-files) Single file/buffer This fixes the bug for now, but it needs to be tested more carefully. And now the view dispatcher has a minor bug when changing the list of buffers-files sometimes that requires pressing it more than once to get the prompt; not sure if related to this. --- org-ql-view.el | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index b966d14..6ed7831 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -827,16 +827,20 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." (string (expand-file-name it)) (otherwise it)) list))) - (pcase (expand-files buffers-files) - ((or (pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) - (pred (seq-set-equal-p (mapcar #'expand-file-name org-agenda-files)))) - "org-agenda-files") - ((pred (seq-set-equal-p (org-ql-search-directories-files))) - "org-directory") + ;; TODO: Test this more exhaustively. + (pcase buffers-files + ((pred listp) (pcase (expand-files buffers-files) + ((or (pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) + (pred (seq-set-equal-p (mapcar #'expand-file-name org-agenda-files)))) + "org-agenda-files") + ((pred (seq-set-equal-p (org-ql-search-directories-files))) + "org-directory") + (_ (let ((print-length nil)) + (concat "'" (prin1-to-string buffers-files)))))) ((pred (equal (current-buffer))) "buffer") (_ (let ((print-length nil)) - (concat "'" (prin1-to-string buffers-files))))))) + (prin1-to-string buffers-files)))))) (defun org-ql-view--complete-buffers-files () "Return value for `org-ql-view-buffers-files' using completion." From 11a0466f92d5791e12f9122deffcd1c8592d327a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Mar 2020 00:45:27 -0600 Subject: [PATCH 118/560] Fix: (helm-org-ql-map) Use make-composed-keymap Fixes #99. Thanks to Akira Komamura (@akirak). --- helm-org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index 2e4ffb8..b954b09 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -56,13 +56,13 @@ ;;;; Variables (defvar helm-org-ql-map - (let ((map (copy-keymap helm-map)) + (let ((map (make-sparse-keymap)) (mappings '( "C-x C-s" helm-org-ql-save ))) (cl-loop for (key fn) on mappings by #'cddr do (define-key map (kbd key) fn)) - map) + (make-composed-keymap map helm-map)) "Keymap for `helm-org-ql' sessions. Based on `helm-map'.") From 06481960764a55a36d886e1db79a58258d5d2ffb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Mar 2020 00:53:41 -0600 Subject: [PATCH 119/560] Change/Fix: (helm-org-ql.el) Wrap in eval-and-compile This avoids errors when Helm is not installed, and it seems to work correctly when Helm is installed. This should be an improvement until this file is put in its own package. --- helm-org-ql.el | 270 +++++++++++++++++++++++++------------------------ 1 file changed, 136 insertions(+), 134 deletions(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index b954b09..059a965 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -28,83 +28,85 @@ ;;; Code: -;;;; Requirements +(eval-and-compile -(require 'org) + (eval-when-compile + ;; Require these when compiling, but not necessarily on load. + (require 'org) -(require 'org-ql) -(require 'org-ql-search) - -;; (require 'helm) -;; (require 'helm-org) + (require 'org-ql) + (require 'org-ql-search)) ;;;; Compatibility -;; Declare Helm functions since Helm may not be installed. -(declare-function helm "ext:helm") -(declare-function helm-run-after-exit "ext:helm") -(declare-function helm-window "ext:helm-lib") -(declare-function helm-buffer-get "ext:helm-lib") -(declare-function helm-make-source "ext:helm-source") -(declare-function helm-org-goto-marker "ext:helm-org") + ;; Declare Helm functions since Helm may not be installed. + (declare-function helm "ext:helm") + (declare-function helm-run-after-exit "ext:helm") + (declare-function helm-window "ext:helm-lib") + (declare-function helm-buffer-get "ext:helm-lib") + (declare-function helm-make-source "ext:helm-source") + (declare-function helm-org-goto-marker "ext:helm-org") -;; Silence byte-compiler about variables. -(defvar helm-map) -(defvar helm-pattern) -(defvar helm-input-idle-delay) + ;; Silence byte-compiler about variables. + (defvar helm-map) + (defvar helm-pattern) + (defvar helm-input-idle-delay) + + (when (require 'helm nil 'noerror) + + ;; Requirements. + (require 'helm-org) ;;;; Variables -(defvar helm-org-ql-map - (let ((map (make-sparse-keymap)) - (mappings '( - "C-x C-s" helm-org-ql-save - ))) - (cl-loop for (key fn) on mappings by #'cddr - do (define-key map (kbd key) fn)) - (make-composed-keymap map helm-map)) - "Keymap for `helm-org-ql' sessions. + (defvar helm-org-ql-map + (let ((map (make-sparse-keymap)) + (mappings '("C-x C-s" helm-org-ql-save))) + (cl-loop for (key fn) on mappings by #'cddr + do (define-key map (kbd key) fn)) + (make-composed-keymap map helm-map)) + "Keymap for `helm-org-ql' sessions. Based on `helm-map'.") -(defvar helm-source-org-ql-views - (helm-make-source "Org QL Views" 'helm-source-sync - :candidates (lambda () - (->> org-ql-views - (-map #'car) - (-sort #'string<))) - :action (list (cons "Show view" #'org-ql-view))) - "Helm source for `org-ql-views'.") + (defvar helm-source-org-ql-views + (helm-make-source "Org QL Views" 'helm-source-sync + :candidates (lambda () + (->> org-ql-views + (-map #'car) + (-sort #'string<))) + :action (list (cons "Show view" #'org-ql-view))) + "Helm source for `org-ql-views'.") -(defvar-local helm-org-ql-buffers-files nil - "Used for `helm-org-ql-save'.") + (defvar-local helm-org-ql-buffers-files nil + "Used for `helm-org-ql-save'.") ;;;; Customization -(defgroup helm-org-ql nil - "Options for `helm-org-ql'." - :group 'org-ql) + (defgroup helm-org-ql nil + "Options for `helm-org-ql'." + :group 'org-ql) -(defcustom helm-org-ql-reverse-paths t - "Whether to reverse Org outline paths in `helm-org-ql' results." - :type 'boolean) + (defcustom helm-org-ql-reverse-paths t + "Whether to reverse Org outline paths in `helm-org-ql' results." + :type 'boolean) -(defcustom helm-org-ql-input-idle-delay 0.25 - "Seconds to wait after typing stops before running query." - :type 'number) + (defcustom helm-org-ql-input-idle-delay 0.25 + "Seconds to wait after typing stops before running query." + :type 'number) -(defcustom helm-org-ql-actions - (list (cons "Show heading in source buffer" 'helm-org-ql-show-marker) - (cons "Show heading in indirect buffer" 'helm-org-ql-show-marker-indirect)) - "Alist of actions for `helm-org-ql' commands." - :type '(alist :key-type (string :tag "Description") - :value-type (function :tag "Command"))) + (defcustom helm-org-ql-actions + (list (cons "Show heading in source buffer" 'helm-org-ql-show-marker) + (cons "Show heading in indirect buffer" 'helm-org-ql-show-marker-indirect)) + "Alist of actions for `helm-org-ql' commands." + :type '(alist :key-type (string :tag "Description") + :value-type (function :tag "Command"))) ;;;; Commands ;;;###autoload -(cl-defun helm-org-ql (buffers-files - &key (boolean 'and) (name "helm-org-ql")) - "Display results in BUFFERS-FILES for an `org-ql' non-sexp query using Helm. + (cl-defun helm-org-ql (buffers-files + &key (boolean 'and) (name "helm-org-ql")) + "Display results in BUFFERS-FILES for an `org-ql' non-sexp query using Helm. Interactively, search the current buffer. Note that this command only accepts non-sexp, \"plain\" queries. @@ -131,99 +133,99 @@ However, quoted strings remain quoted, so this input: Is transformed into this query: (and \"something else\" (tags \"funny\"))" - (interactive (list (current-buffer))) - (let ((boolean (if current-prefix-arg 'or boolean)) - (helm-input-idle-delay helm-org-ql-input-idle-delay)) - (helm :prompt (format "Query (boolean %s): " (-> boolean symbol-name upcase)) - :sources (helm-org-ql-source buffers-files :name name)))) + (interactive (list (current-buffer))) + (let ((boolean (if current-prefix-arg 'or boolean)) + (helm-input-idle-delay helm-org-ql-input-idle-delay)) + (helm :prompt (format "Query (boolean %s): " (-> boolean symbol-name upcase)) + :sources (helm-org-ql-source buffers-files :name name)))) ;;;###autoload -(defun helm-org-ql-agenda-files () - "Search agenda files with `helm-org-ql', which see." - (interactive) - (helm-org-ql (org-agenda-files) :name "Org Agenda Files")) + (defun helm-org-ql-agenda-files () + "Search agenda files with `helm-org-ql', which see." + (interactive) + (helm-org-ql (org-agenda-files) :name "Org Agenda Files")) ;;;###autoload -(defun helm-org-ql-org-directory () - "Search Org files in `org-directory' with `helm-org-ql'." - (interactive) - (helm-org-ql (org-ql-search-directories-files) - :name "Org Directory Files")) + (defun helm-org-ql-org-directory () + "Search Org files in `org-directory' with `helm-org-ql'." + (interactive) + (helm-org-ql (org-ql-search-directories-files) + :name "Org Directory Files")) -(defun helm-org-ql-show-marker (marker) - "Show heading at MARKER." - (interactive) - ;; This function is necessary because `helm-org-goto-marker' calls - ;; `re-search-backward' to go backward to the start of a heading, - ;; which, when the marker is already at the desired heading, causes - ;; it to go to the previous heading. I don't know why it does that. - (switch-to-buffer (marker-buffer marker)) - (goto-char marker) - (org-show-entry)) + (defun helm-org-ql-show-marker (marker) + "Show heading at MARKER." + (interactive) + ;; This function is necessary because `helm-org-goto-marker' calls + ;; `re-search-backward' to go backward to the start of a heading, + ;; which, when the marker is already at the desired heading, causes + ;; it to go to the previous heading. I don't know why it does that. + (switch-to-buffer (marker-buffer marker)) + (goto-char marker) + (org-show-entry)) -(defun helm-org-ql-show-marker-indirect (marker) - "Show heading at MARKER with `org-tree-to-indirect-buffer'." - (interactive) - (helm-org-ql-show-marker marker) - (org-tree-to-indirect-buffer)) + (defun helm-org-ql-show-marker-indirect (marker) + "Show heading at MARKER with `org-tree-to-indirect-buffer'." + (interactive) + (helm-org-ql-show-marker marker) + (org-tree-to-indirect-buffer)) -(defun helm-org-ql-save () - "Show `helm-org-ql' search in an `org-ql-search' buffer." - (interactive) - (let ((buffers-files (with-current-buffer (helm-buffer-get) - helm-org-ql-buffers-files)) - (query (org-ql--plain-query helm-pattern))) - (helm-run-after-exit #'org-ql-search buffers-files query))) + (defun helm-org-ql-save () + "Show `helm-org-ql' search in an `org-ql-search' buffer." + (interactive) + (let ((buffers-files (with-current-buffer (helm-buffer-get) + helm-org-ql-buffers-files)) + (query (org-ql--plain-query helm-pattern))) + (helm-run-after-exit #'org-ql-search buffers-files query))) ;;;###autoload -(defun helm-org-ql-views () - "Show an `org-ql' view selected with Helm." - (interactive) - (helm :sources helm-source-org-ql-views)) + (defun helm-org-ql-views () + "Show an `org-ql' view selected with Helm." + (interactive) + (helm :sources helm-source-org-ql-views)) ;;;; Functions -(cl-defun helm-org-ql-source (buffers-files &key (name "helm-org-ql")) - "Return Helm source named NAME that searches BUFFERS-FILES with `helm-org-ql'." - ;; Expansion of `helm-build-sync-source' macro. - (helm-make-source name 'helm-source-sync - :candidates (lambda () - (let* ((query (org-ql--plain-query helm-pattern)) - (window-width (window-width (helm-window)))) - (when query - (with-current-buffer (helm-buffer-get) - (setq helm-org-ql-buffers-files buffers-files)) - (ignore-errors - ;; Ignore errors that might be caused by partially typed queries. - (org-ql-select buffers-files query - :action `(helm-org-ql--heading ,window-width)))))) - :match #'identity - :fuzzy-match nil - :multimatch nil - :nohighlight t - :volatile t - :keymap helm-org-ql-map - :action helm-org-ql-actions)) + (cl-defun helm-org-ql-source (buffers-files &key (name "helm-org-ql")) + "Return Helm source named NAME that searches BUFFERS-FILES with `helm-org-ql'." + ;; Expansion of `helm-build-sync-source' macro. + (helm-make-source name 'helm-source-sync + :candidates (lambda () + (let* ((query (org-ql--plain-query helm-pattern)) + (window-width (window-width (helm-window)))) + (when query + (with-current-buffer (helm-buffer-get) + (setq helm-org-ql-buffers-files buffers-files)) + (ignore-errors + ;; Ignore errors that might be caused by partially typed queries. + (org-ql-select buffers-files query + :action `(helm-org-ql--heading ,window-width)))))) + :match #'identity + :fuzzy-match nil + :multimatch nil + :nohighlight t + :volatile t + :keymap helm-org-ql-map + :action helm-org-ql-actions)) -(defun helm-org-ql--heading (window-width) - "Return string for Helm for heading at point. + (defun helm-org-ql--heading (window-width) + "Return string for Helm for heading at point. WINDOW-WIDTH should be the width of the Helm window." - (font-lock-ensure (point-at-bol) (point-at-eol)) - ;; TODO: It would be better to avoid calculating the prefix and width - ;; at each heading, but there's no easy way to do that once in each - ;; buffer, unless we manually called `org-ql' in each buffer, which - ;; I'd prefer not to do. Maybe I should add a feature to `org-ql' to - ;; call a setup function in a buffer before running queries. - (let* ((prefix (concat (buffer-name) ":")) - (width (- window-width (length prefix))) - (heading (org-get-heading t)) - (path (-> (org-get-outline-path) - (org-format-outline-path width nil "") - (org-split-string ""))) - (path (if helm-org-ql-reverse-paths - (concat heading "\\" (s-join "\\" (nreverse path))) - (concat (s-join "/" path) "/" heading)))) - (cons (concat prefix path) (point-marker)))) + (font-lock-ensure (point-at-bol) (point-at-eol)) + ;; TODO: It would be better to avoid calculating the prefix and width + ;; at each heading, but there's no easy way to do that once in each + ;; buffer, unless we manually called `org-ql' in each buffer, which + ;; I'd prefer not to do. Maybe I should add a feature to `org-ql' to + ;; call a setup function in a buffer before running queries. + (let* ((prefix (concat (buffer-name) ":")) + (width (- window-width (length prefix))) + (heading (org-get-heading t)) + (path (-> (org-get-outline-path) + (org-format-outline-path width nil "") + (org-split-string ""))) + (path (if helm-org-ql-reverse-paths + (concat heading "\\" (s-join "\\" (nreverse path))) + (concat (s-join "/" path) "/" heading)))) + (cons (concat prefix path) (point-marker)))))) ;;;; Footer From 8aac3b61001f25d04e6a1fdfe03be0509b50ae83 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Mar 2020 11:05:20 -0500 Subject: [PATCH 120/560] Fix: (org-ql-view-map) Use set-keymap-parent --- org-ql-view.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index 6ed7831..9f550f4 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -70,7 +70,8 @@ Includes `org-ql-search'. Helpful when passing a buffer argument down a chain of function calls would be awkward.") (defvar org-ql-view-map - (let ((map (copy-keymap org-agenda-mode-map))) + (let ((map (make-sparse-keymap))) + (set-keymap-parent map org-agenda-mode-map) (define-key map "r" #'org-ql-view-refresh) (define-key map "v" #'org-ql-view-dispatch) (define-key map (kbd "C-x C-s") #'org-ql-view-save) From 3349c1d07afb7ee88b1fee4ddb78f0cb1084f4e7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Mar 2020 11:05:38 -0500 Subject: [PATCH 121/560] Change: (org-ql-view-map) Also bind "g" to refresh I keep hitting "g" and nothing seems to happen, because it runs the org-agenda refresh command, which doesn't do anything in org-ql-view buffers. This must be happening to other people too. So let's fix that. --- README.org | 2 +- org-ql-view.el | 1 + org-ql.info | 58 +++++++++++++++++++++++++------------------------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/README.org b/README.org index 63ca963..e2c08a0 100644 --- a/README.org +++ b/README.org @@ -132,7 +132,7 @@ This command displays matches with Helm. *Note:* Helm is not a package dependen Choose and display a view stored in ~org-ql-views~. *Bindings:* Keys bound in view buffer. -+ =r=: Refresh results. With prefix, prompt to adjust search parameters. ++ =g=, =r=: Refresh results. With prefix, prompt to adjust search parameters. + =v=: Show =transient= view dispatcher (like Magit's popups). + =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). diff --git a/org-ql-view.el b/org-ql-view.el index 9f550f4..941225b 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -72,6 +72,7 @@ down a chain of function calls would be awkward.") (defvar org-ql-view-map (let ((map (make-sparse-keymap))) (set-keymap-parent map org-agenda-mode-map) + (define-key map "g" #'org-ql-view-refresh) (define-key map "r" #'org-ql-view-refresh) (define-key map "v" #'org-ql-view-dispatch) (define-key map (kbd "C-x C-s") #'org-ql-view-save) diff --git a/org-ql.info b/org-ql.info index 6f5744c..d700130 100644 --- a/org-ql.info +++ b/org-ql.info @@ -254,7 +254,7 @@ File: README.info, Node: org-ql-view, Next: org-ql-view-sidebar, Prev: helm-o Choose and display a view stored in ‘org-ql-views’. *Bindings:* Keys bound in view buffer. - • r: Refresh results. With prefix, prompt to adjust search + • g, r: Refresh results. With prefix, prompt to adjust search parameters. • v: Show transient view dispatcher (like Magit’s popups). • C-x C-s: Save query to variable ‘org-ql-views’ (accessible with @@ -1119,34 +1119,34 @@ Node: Commands3123 Node: org-ql-search3596 Node: helm-org-ql5310 Node: org-ql-view5722 -Node: org-ql-view-sidebar6219 -Node: org-ql-view-recent-items6575 -Node: org-ql-sparse-tree7059 -Node: Queries7859 -Node: Non-sexp query syntax8767 -Node: General predicates10474 -Node: Ancestor/descendant predicates15689 -Node: Date/time predicates16817 -Node: Functions / Macros19472 -Node: Agenda-like views19705 -Node: Listing / acting-on results21110 -Node: Changelog25712 -Node: 05-pre26291 -Node: 04226655 -Node: 04126817 -Node: 0427056 -Node: 03230987 -Node: 03131364 -Node: 0331559 -Node: 02334532 -Node: 02234758 -Node: 02135024 -Node: 0235223 -Node: 0139258 -Node: Notes39359 -Node: Comparison with Org Agenda searches39521 -Node: org-sidebar40393 -Node: License40672 +Node: org-ql-view-sidebar6222 +Node: org-ql-view-recent-items6578 +Node: org-ql-sparse-tree7062 +Node: Queries7862 +Node: Non-sexp query syntax8770 +Node: General predicates10477 +Node: Ancestor/descendant predicates15692 +Node: Date/time predicates16820 +Node: Functions / Macros19475 +Node: Agenda-like views19708 +Node: Listing / acting-on results21113 +Node: Changelog25715 +Node: 05-pre26294 +Node: 04226658 +Node: 04126820 +Node: 0427059 +Node: 03230990 +Node: 03131367 +Node: 0331562 +Node: 02334535 +Node: 02234761 +Node: 02135027 +Node: 0235226 +Node: 0139261 +Node: Notes39362 +Node: Comparison with Org Agenda searches39524 +Node: org-sidebar40396 +Node: License40675  End Tag Table From 996d6485603a9e2a22edaf8343291615c5884d0f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Mar 2020 11:12:49 -0500 Subject: [PATCH 122/560] Fix: (org-ql-view--contract-buffers-files) Handle org-agenda-files --- org-ql-view.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index 941225b..20eb02e 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -841,6 +841,8 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." (concat "'" (prin1-to-string buffers-files)))))) ((pred (equal (current-buffer))) "buffer") + ((or 'org-agenda-files '(function org-agenda-files)) + "org-agenda-files") (_ (let ((print-length nil)) (prin1-to-string buffers-files)))))) From f7d8b8c78c4b20d9c4f1a4d45f35171c95fd1ac6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Mar 2020 13:31:22 -0500 Subject: [PATCH 123/560] Fix: (org-ql-view-map) Bind q to bury-buffer Because org-agenda-quit isn't useful in org-ql-view buffers. --- org-ql-view.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-view.el b/org-ql-view.el index 20eb02e..58cbd61 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -74,6 +74,7 @@ down a chain of function calls would be awkward.") (set-keymap-parent map org-agenda-mode-map) (define-key map "g" #'org-ql-view-refresh) (define-key map "r" #'org-ql-view-refresh) + (define-key map "q" #'bury-buffer) (define-key map "v" #'org-ql-view-dispatch) (define-key map (kbd "C-x C-s") #'org-ql-view-save) map) From 1688774dddae45b7b77420d01c0eb56d76dd0c95 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Mar 2020 17:37:17 -0500 Subject: [PATCH 124/560] Change: (org-ql-view--header-line-format) Use keyword args --- org-ql-search.el | 6 ++++-- org-ql-view.el | 43 +++++++++++++++++++++++++------------------ 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index 10d3fcf..f84dfed 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -164,7 +164,8 @@ necessary." :sort sort)) (strings (-map #'org-ql-view--format-element results)) (buffer (or buffer (format "%s %s*" org-ql-view-buffer-name-prefix (or title query)))) - (header (org-ql-view--header-line-format buffers-files query title)) + (header (org-ql-view--header-line-format + :buffers-files buffers-files :query query :title title)) ;; Bind variables for `org-ql-view--display' to set. (org-ql-view-buffers-files buffers-files) (org-ql-view-query query) @@ -215,7 +216,8 @@ automatically from the query." ;; FIXME: `org-agenda--insert-overriding-header' is from an Org version newer than ;; I'm using. Should probably declare it as a minimum Org version after upgrading. ;; (org-agenda--insert-overriding-header (or org-ql-block-header (org-ql-agenda--header-line-format from query))) - (insert (org-add-props (or org-ql-block-header (org-ql-view--header-line-format from query)) + (insert (org-add-props (or org-ql-block-header (org-ql-view--header-line-format + :buffers-files from :query query)) nil 'face 'org-agenda-structure) "\n") ;; Calling `org-agenda-finalize' should be unnecessary, because in a "series" agenda, ;; `org-agenda-multi' is bound non-nil, in which case `org-agenda-finalize' does nothing. diff --git a/org-ql-view.el b/org-ql-view.el index 58cbd61..9ae7e1e 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -433,31 +433,38 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', (org-agenda-finalize) (goto-char (point-min)))))) -(defun org-ql-view--header-line-format (buffers-files query &optional title) +(cl-defun org-ql-view--header-line-format (&key buffers-files query title) "Return `header-line-format' for BUFFERS-FILES and QUERY. If TITLE, prepend it to the header." (let* ((title (if title (concat (propertize "View:" 'face 'transient-argument) title " ") "")) - (query-formatted (org-ql-view--format-query query)) - (query-width (length query-formatted)) - (query-propertized (propertize (org-ql-view--font-lock-string 'emacs-lisp-mode query-formatted) - 'help-echo query-formatted)) - (available-width (max 0 (- (window-width) - (length "In: ") - (length "Query: ") - query-width 4))) - (buffers-files-formatted (format "%s" (org-ql-view--contract-buffers-files buffers-files))) - (buffers-files-formatted (propertize (->> buffers-files-formatted - (org-ql-view--font-lock-string 'emacs-lisp-mode) - (s-truncate available-width)) - 'help-echo buffers-files-formatted))) + (query-formatted (when query + (org-ql-view--format-query query))) + (query-width (when query-formatted + (length query-formatted))) + (query-propertized (when query-formatted + (propertize (org-ql-view--font-lock-string 'emacs-lisp-mode query-formatted) + 'help-echo query-formatted))) + (available-width (max 0 (- (window-width) (length "In: ") + (length "Query: ") (or query-width 0) + 4))) + (buffers-files-formatted (when buffers-files + (format "%s" (org-ql-view--contract-buffers-files buffers-files)))) + (buffers-files-formatted (when buffers-files-formatted + (propertize (->> buffers-files-formatted + (org-ql-view--font-lock-string 'emacs-lisp-mode) + (s-truncate available-width)) + 'help-echo buffers-files-formatted)))) (concat title - (propertize "Query:" 'face 'transient-argument) - query-propertized " " - (propertize "In:" 'face 'transient-argument) - buffers-files-formatted))) + (when query (propertize "Query:" 'face 'transient-argument)) + (when query query-propertized) + (when query " ") + (when buffers-files + (propertize "In:" 'face 'transient-argument)) + (when buffers-files-formatted + buffers-files-formatted)))) (defun org-ql-view--format-query (query) "Return QUERY formatted as a string. From 881d298cd07fe3da487b65e531a65ad35f2a7767 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 13 Mar 2020 19:07:30 -0500 Subject: [PATCH 125/560] Comment: Add TODOs --- org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql.el b/org-ql.el index 0853659..a03f6d6 100644 --- a/org-ql.el +++ b/org-ql.el @@ -133,6 +133,7 @@ This list should not contain any duplicates.") (defgroup org-ql nil "Customization for `org-ql'." :group 'org + ;; TODO: Add info manual link. :link '(url-link "https://github.com/alphapapa/org-ql")) ;;;; Macros @@ -160,6 +161,7 @@ match." (push (list :name ',pred-name :aliases ',aliases :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates) (cl-defun ,fn-name ,args ,docstring ,@body)))) +;; TODO: Mark as obsolete/deprecated. ;;;###autoload (cl-defmacro org-ql (buffers-or-files query &key sort narrow action) "Expands into a call to `org-ql-select' with the same arguments. From ca03ad0d4a709c2a4b09e796e7bfcdc72b5064f8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Mar 2020 14:01:35 -0500 Subject: [PATCH 126/560] Meta: Update makem.sh --- makem.sh | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/makem.sh b/makem.sh index 3fddb78..91c3000 100755 --- a/makem.sh +++ b/makem.sh @@ -60,6 +60,7 @@ Rules: lint-checkdoc Run checkdoc. lint-compile Byte-compile source files with warnings as errors. lint-declare Run check-declare. + lint-elsa Run Elsa (not included in "lint" rule). lint-indent Lint indentation. lint-package Run package-lint. lint-regexps Run relint. @@ -478,8 +479,10 @@ function sandbox { then debug "Installing linters: package-lint relint" - args_sandbox_package_install+=(--eval "(package-install 'package-lint)" - --eval "(package-install 'relint)") + args_sandbox_package_install+=( + --eval "(package-install 'elsa)" + --eval "(package-install 'package-lint)" + --eval "(package-install 'relint)") fi # *** Install packages into sandbox @@ -671,8 +674,9 @@ function compile { } function batch { - # Run Emacs with $args_batch and with project source and test files loaded. - verbose 1 "Executing Emacs with arguments: ${args_batch[@]}" + # Run Emacs in batch mode with ${args_batch_interactive[@]} and + # with project source and test files loaded. + verbose 1 "Executing Emacs with arguments: ${args_batch_interactive[@]}" run_emacs \ $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ @@ -681,6 +685,9 @@ function batch { function interactive { # Run Emacs interactively. Most useful with --sandbox and --install-deps. + verbose 1 "Running Emacs interactively..." + verbose 2 "Loading files:" "${files_project_feature[@]}" "${files_project_test[@]}" + unset arg_batch run_emacs \ $(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ @@ -737,6 +744,20 @@ function lint-declare { || error "Linting declarations failed." } +function lint-elsa { + verbose 1 "Linting with Elsa..." + + # MAYBE: Install Elsa here rather than in sandbox init, to avoid installing + # it when not needed. However, we should be careful to be clear about when + # packages are installed, because installing them does execute code. + run_emacs \ + --load elsa \ + -f elsa-run-files-and-exit \ + "${files_project_feature[@]}" \ + && success "Linting with Elsa finished without errors." \ + || error "Linting with Elsa failed." +} + function lint-indent { verbose 1 "Linting indentation..." @@ -952,8 +973,7 @@ do ;; -f|--file) shift - project_source_files+=("$1") - project_byte_compile_files+=("$1") + args_files+=("$1") ;; -O|--no-org-repo) unset elisp_org_package_archive @@ -991,6 +1011,13 @@ files_project_feature=($(files-project-feature)) files_project_test=($(files-project-test)) files_project_byte_compile=("${files_project_feature[@]}" "${files_project_test[@]}") +if [[ ${args_files[@]} ]] +then + # Add specified files. + files_project_feature+=("${args_files[@]}") + files_project_byte_compile+=("${args_files[@]}") +fi + debug "EXCLUDING FILES: ${files_exclude[@]}" debug "FEATURE FILES: ${files_project_feature[@]}" debug "TEST FILES: ${files_project_test[@]}" From ba7d4a2e82f134b8bb9976c81227ec795dde00d4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Mar 2020 13:53:46 -0500 Subject: [PATCH 127/560] Add/Fix: org-ql-view-mode, and check when refreshing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a derived major mode for org-ql-view buffers, and ensure that mode is active when calling org-ql-view-refresh, to avoid interfering with buffers in other modes if the user calls the command by accident. See . Thanks to Alois Janíček (@AloisJanicek) for discovering the bug. Released as 0.4.3. --- README.org | 5 +++ org-ql-view.el | 11 +++-- org-ql.el | 2 +- org-ql.info | 115 +++++++++++++++++++++++++++---------------------- 4 files changed, 77 insertions(+), 56 deletions(-) diff --git a/README.org b/README.org index 180138f..2cc2550 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.3 + +*Fixed* ++ When =org-ql-view-refresh= is called, ensure the buffer is an Org QL View buffer. + ** 0.4.2 *Fixed* diff --git a/org-ql-view.el b/org-ql-view.el index 1a132d7..bbcccf1 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -309,6 +309,8 @@ TYPE may be `ts', `ts-active', `ts-inactive', `clocked', or If PROMPT is non-nil (interactively, with prefix), prompt to update search arguments." (interactive "P") + (unless (eq major-mode 'org-ql-view-mode) + (user-error "Not an Org QL View buffer")) (let* ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) (old-pos (point)) (defaults (list org-ql-view-buffers-files @@ -354,6 +356,10 @@ update search arguments." ;;;; Functions +(define-derived-mode org-ql-view-mode org-agenda-mode "Org QL View" + "Major mode for `org-ql-view' buffers." + (setf buffer-read-only t)) + (defun org-ql-view--list-buffer () "Return view list buffer." (with-current-buffer (get-buffer-create "*Org QL View List*") @@ -468,9 +474,8 @@ with human-readable strings." If NAME is non-nil, return buffer by that name instead of using default buffer." (with-current-buffer (get-buffer-create (or name (concat org-ql-view-buffer-name-prefix "*"))) - (unless (eq major-mode 'org-agenda-mode) - (org-agenda-mode) - (setf buffer-read-only t)) + (unless (eq major-mode 'org-ql-view-mode) + (org-ql-view-mode)) (current-buffer))) (defun org-ql-view--format-relative-date (difference) diff --git a/org-ql.el b/org-ql.el index 65f1053..4f89b1c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.2 +;; Version: 0.4.3 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index a64db08..e763688 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.3: 043. * 0.4.2: 042. * 0.4.1: 041. * 0.4: 04. @@ -95,9 +96,7 @@ File: README.info, Node: Contents, Next: Screenshots, Prev: Top, Up: Top 1 Contents ********** - • • • - • • - • • • • • • + • • • • •  File: README.info, Node: Screenshots, Next: Installation, Prev: Contents, Up: Top @@ -705,6 +704,7 @@ releases. * Menu: +* 0.4.3: 043. * 0.4.2: 042. * 0.4.1: 041. * 0.4: 04. @@ -718,9 +718,19 @@ releases. * 0.1: 01.  -File: README.info, Node: 042, Next: 041, Up: Changelog +File: README.info, Node: 043, Next: 042, Up: Changelog -5.1 0.4.2 +5.1 0.4.3 +========= + +*Fixed* + • When org-ql-view-refresh is called, ensure the buffer is an Org QL + View buffer. + + +File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog + +5.2 0.4.2 ========= *Fixed* @@ -729,7 +739,7 @@ File: README.info, Node: 042, Next: 041, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.2 0.4.1 +5.3 0.4.1 ========= *Fixed* @@ -739,7 +749,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.3 0.4 +5.4 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -820,7 +830,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.4 0.3.2 +5.5 0.3.2 ========= *Fixed* @@ -833,7 +843,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.5 0.3.1 +5.6 0.3.1 ========= *Fixed* @@ -843,7 +853,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.6 0.3 +5.7 0.3 ======= *Added* @@ -908,7 +918,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.7 0.2.3 +5.8 0.2.3 ========= *Fixed* @@ -918,7 +928,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.8 0.2.2 +5.9 0.2.2 ========= *Fixed* @@ -929,8 +939,8 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.9 0.2.1 -========= +5.10 0.2.1 +========== *Fixed* • (descendants) selector matched against parent heading instead of @@ -939,7 +949,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.10 0.2 +5.11 0.2 ======== *Added* @@ -1022,7 +1032,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.11 0.1 +5.12 0.1 ======== First tagged release. @@ -1083,42 +1093,43 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1432 -Node: Screenshots1606 -Node: Installation1724 -Node: Quelpa2362 -Node: Usage2805 -Node: Commands3154 -Node: org-ql-search3627 -Node: helm-org-ql5275 -Node: org-ql-view5687 -Node: org-ql-view-sidebar5885 -Node: org-ql-view-recent-items6241 -Node: org-ql-sparse-tree6725 -Node: Queries7525 -Node: Non-sexp query syntax8433 -Node: General predicates10140 -Node: Ancestor/descendant predicates14947 -Node: Date/time predicates16075 -Node: Functions / Macros18730 -Node: Agenda-like views18963 -Node: Listing / acting-on results20368 -Node: Changelog24970 -Node: 04225529 -Node: 04125676 -Node: 0425915 -Node: 03229846 -Node: 03130223 -Node: 0330418 -Node: 02333391 -Node: 02233617 -Node: 02133883 -Node: 0234080 -Node: 0138115 -Node: Notes38216 -Node: Comparison with Org Agenda searches38378 -Node: org-sidebar39249 -Node: License39528 +Node: Contents1447 +Node: Screenshots1574 +Node: Installation1692 +Node: Quelpa2330 +Node: Usage2773 +Node: Commands3122 +Node: org-ql-search3595 +Node: helm-org-ql5243 +Node: org-ql-view5655 +Node: org-ql-view-sidebar5853 +Node: org-ql-view-recent-items6209 +Node: org-ql-sparse-tree6693 +Node: Queries7493 +Node: Non-sexp query syntax8401 +Node: General predicates10108 +Node: Ancestor/descendant predicates14915 +Node: Date/time predicates16043 +Node: Functions / Macros18698 +Node: Agenda-like views18931 +Node: Listing / acting-on results20336 +Node: Changelog24938 +Node: 04325512 +Node: 04225695 +Node: 04125854 +Node: 0426093 +Node: 03230024 +Node: 03130401 +Node: 0330596 +Node: 02333569 +Node: 02233795 +Node: 02134061 +Node: 0234260 +Node: 0138295 +Node: Notes38396 +Node: Comparison with Org Agenda searches38558 +Node: org-sidebar39429 +Node: License39708  End Tag Table From 4fef5b089f8f77b0dc25dac5f096406156e90858 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 15 Mar 2020 14:58:06 -0500 Subject: [PATCH 128/560] Fix/Revert: Don't derive a new mode; check a variable in refresh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a different major mode in org-ql-view buffers causes some Org Agenda remote commands to not work, because they test whether the major mode is org-agenda-mode. Even though these remote commands are not guaranteed to work, it was not intended to break them now, so this restores compatibility with them. Fixes #102. Thanks to Alois Janíček (@aloisjanicek) for reporting. This reverts commit ba7d4a2e82f134b8bb9976c81227ec795dde00d4. Released as 0.4.4. --- README.org | 5 ++ org-ql-view.el | 11 ++--- org-ql.el | 2 +- org-ql.info | 124 ++++++++++++++++++++++++++++--------------------- 4 files changed, 80 insertions(+), 62 deletions(-) diff --git a/README.org b/README.org index 2cc2550..d6e654b 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.4 + +*Fixed* ++ Compatibility with Org Agenda remote editing commands (some of which were broken by 0.4.3). (Fixes [[https://github.com/alphapapa/org-ql/issues/102][#102]]. Thanks to [[https://github.com/AloisJanicek][Alois Janíček]] for reporting.) + ** 0.4.3 *Fixed* diff --git a/org-ql-view.el b/org-ql-view.el index bbcccf1..2d86c91 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -309,7 +309,7 @@ TYPE may be `ts', `ts-active', `ts-inactive', `clocked', or If PROMPT is non-nil (interactively, with prefix), prompt to update search arguments." (interactive "P") - (unless (eq major-mode 'org-ql-view-mode) + (unless org-ql-view-buffers-files (user-error "Not an Org QL View buffer")) (let* ((current-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) (old-pos (point)) @@ -356,10 +356,6 @@ update search arguments." ;;;; Functions -(define-derived-mode org-ql-view-mode org-agenda-mode "Org QL View" - "Major mode for `org-ql-view' buffers." - (setf buffer-read-only t)) - (defun org-ql-view--list-buffer () "Return view list buffer." (with-current-buffer (get-buffer-create "*Org QL View List*") @@ -474,8 +470,9 @@ with human-readable strings." If NAME is non-nil, return buffer by that name instead of using default buffer." (with-current-buffer (get-buffer-create (or name (concat org-ql-view-buffer-name-prefix "*"))) - (unless (eq major-mode 'org-ql-view-mode) - (org-ql-view-mode)) + (unless (eq major-mode 'org-agenda-mode) + (org-agenda-mode) + (setf buffer-read-only t)) (current-buffer))) (defun org-ql-view--format-relative-date (difference) diff --git a/org-ql.el b/org-ql.el index 4f89b1c..aef1854 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.3 +;; Version: 0.4.4 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index e763688..5919d5e 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.4: 044. * 0.4.3: 043. * 0.4.2: 042. * 0.4.1: 041. @@ -96,7 +97,9 @@ File: README.info, Node: Contents, Next: Screenshots, Prev: Top, Up: Top 1 Contents ********** - • • • • • + • • • + • • + • • • • • •  File: README.info, Node: Screenshots, Next: Installation, Prev: Contents, Up: Top @@ -148,8 +151,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top 4 Usage ******* - • • - • • • • • + • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -704,6 +706,7 @@ releases. * Menu: +* 0.4.4: 044. * 0.4.3: 043. * 0.4.2: 042. * 0.4.1: 041. @@ -718,9 +721,21 @@ releases. * 0.1: 01.  -File: README.info, Node: 043, Next: 042, Up: Changelog +File: README.info, Node: 044, Next: 043, Up: Changelog -5.1 0.4.3 +5.1 0.4.4 +========= + +*Fixed* + • Compatibility with Org Agenda remote editing commands (some of + which were broken by 0.4.3). (Fixes #102 + (https://github.com/alphapapa/org-ql/issues/102). Thanks to Alois + Janíček (https://github.com/AloisJanicek) for reporting.) + + +File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog + +5.2 0.4.3 ========= *Fixed* @@ -730,7 +745,7 @@ File: README.info, Node: 043, Next: 042, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.2 0.4.2 +5.3 0.4.2 ========= *Fixed* @@ -739,7 +754,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.3 0.4.1 +5.4 0.4.1 ========= *Fixed* @@ -749,7 +764,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.4 0.4 +5.5 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -830,7 +845,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.5 0.3.2 +5.6 0.3.2 ========= *Fixed* @@ -843,7 +858,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.6 0.3.1 +5.7 0.3.1 ========= *Fixed* @@ -853,7 +868,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.7 0.3 +5.8 0.3 ======= *Added* @@ -918,7 +933,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.8 0.2.3 +5.9 0.2.3 ========= *Fixed* @@ -928,8 +943,8 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.9 0.2.2 -========= +5.10 0.2.2 +========== *Fixed* • (deadline auto) selector matched entries whose deadlines had a @@ -939,7 +954,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.10 0.2.1 +5.11 0.2.1 ========== *Fixed* @@ -949,7 +964,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.11 0.2 +5.12 0.2 ======== *Added* @@ -1032,7 +1047,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.12 0.1 +5.13 0.1 ======== First tagged release. @@ -1093,43 +1108,44 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1447 -Node: Screenshots1574 -Node: Installation1692 -Node: Quelpa2330 -Node: Usage2773 -Node: Commands3122 -Node: org-ql-search3595 -Node: helm-org-ql5243 -Node: org-ql-view5655 -Node: org-ql-view-sidebar5853 -Node: org-ql-view-recent-items6209 -Node: org-ql-sparse-tree6693 -Node: Queries7493 -Node: Non-sexp query syntax8401 -Node: General predicates10108 -Node: Ancestor/descendant predicates14915 -Node: Date/time predicates16043 -Node: Functions / Macros18698 -Node: Agenda-like views18931 -Node: Listing / acting-on results20336 -Node: Changelog24938 -Node: 04325512 -Node: 04225695 -Node: 04125854 -Node: 0426093 -Node: 03230024 -Node: 03130401 -Node: 0330596 -Node: 02333569 -Node: 02233795 -Node: 02134061 -Node: 0234260 -Node: 0138295 -Node: Notes38396 -Node: Comparison with Org Agenda searches38558 -Node: org-sidebar39429 -Node: License39708 +Node: Contents1462 +Node: Screenshots1636 +Node: Installation1754 +Node: Quelpa2392 +Node: Usage2835 +Node: Commands3163 +Node: org-ql-search3636 +Node: helm-org-ql5284 +Node: org-ql-view5696 +Node: org-ql-view-sidebar5894 +Node: org-ql-view-recent-items6250 +Node: org-ql-sparse-tree6734 +Node: Queries7534 +Node: Non-sexp query syntax8442 +Node: General predicates10149 +Node: Ancestor/descendant predicates14956 +Node: Date/time predicates16084 +Node: Functions / Macros18739 +Node: Agenda-like views18972 +Node: Listing / acting-on results20377 +Node: Changelog24979 +Node: 04425568 +Node: 04325913 +Node: 04226108 +Node: 04126267 +Node: 0426506 +Node: 03230437 +Node: 03130814 +Node: 0331009 +Node: 02333982 +Node: 02234208 +Node: 02134476 +Node: 0234675 +Node: 0138710 +Node: Notes38811 +Node: Comparison with Org Agenda searches38973 +Node: org-sidebar39844 +Node: License40123  End Tag Table From b3ee9a9c08f07c3f139777c58df09e5df7aa3cb8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 20 Mar 2020 15:59:28 -0500 Subject: [PATCH 129/560] Notes: Add tasks, sort --- notes.org | 720 +++++++++++++++++++++++++++--------------------------- 1 file changed, 364 insertions(+), 356 deletions(-) diff --git a/notes.org b/notes.org index b5ae904..9bd04d2 100644 --- a/notes.org +++ b/notes.org @@ -2,6 +2,10 @@ * Tasks +** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate + +It should act like ~(or (deadline auto) (scheduled :to today))~. + ** TODO [#A] Document sorters Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. @@ -28,9 +32,7 @@ Also, should support an ~id~ one. + Added example to =examples.org=. -*** DONE Save query from ql-agenda buffer - -*** DONE Access saved query from saved query list +*** TODO Bookmarks *** TODO Org link types :PROPERTIES: @@ -43,7 +45,265 @@ This would be useful for having a menu of saved queries as Org links, or even bo **** TODO For saved queries -*** TODO Bookmarks +*** DONE Access saved query from saved query list + +*** DONE Save query from ql-agenda buffer + +** UNDERWAY [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. + +** DONE [#A] Helm command + +In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. + +*** DONE Add + +*** DONE Demonstrate + +*** DONE Parsing non-Lisp queries + +[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror)) + ((predicate . args) (nreverse parsed))) + (when predicate + (list :predicate predicate :args args :combinator combinator))) + ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) +#+END_SRC + +I don't know where the =t= is coming from. + +The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (syntax-class whitespace)))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) +#+END_SRC + +In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. + +This seems to work, but we'll have to parse the args again in a separate step: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) +#+END_SRC + +Well, a bit of fiddling (lots of trial-and-error required) produced this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) +#+END_SRC + +That seems pretty usable! + +** TODO [#B] Add more sorters? + ++ [ ] =category= ++ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry + +** TODO [#B] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ + +For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. + +** TODO [#B] Default sort + +Would probably be useful to have a default sort option. + +** TODO [#B] Normalize queries + +[2019-07-16 Tue 11:49] This serves two purposes: + +1. Equivalent queries will return the same results from the cache. +2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file. + +So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. + +** TODO [#B] Quickly change sorting/grouping in search views + +With caching, the search doesn't need to be repeated, so resorting/regrouping can be very fast. + +** TODO [#B] Recursive queries + +For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. + +This works pretty well. It needs polishing, and some refactoring so items can be indented completely (rather than leaving the keyword unindented, as it is now). + +#+BEGIN_SRC elisp + (cl-defun org-ql-agenda-recursive (buffers-or-files queries &key action narrow sort) + (cl-labels ((rec (queries element indent) + (org-with-point-at (org-element-property :org-marker element) + (when-let* ((results (progn + (org-narrow-to-subtree) + (org-ql-select (current-buffer) + (car queries) + :action 'element-with-markers + :narrow t + :sort sort)))) + ;; Indent entry for each level + (setf results (--map + (org-element-put-property it :raw-value + (concat (s-repeat (* 5 indent) " ") + (org-element-property :raw-value it))) + results)) + (cons it (if (cdr queries) + (--map (rec (cdr queries) it) + results) + results)))))) + (when-let* ((indent 0) + (results (org-ql-select buffers-or-files + (car queries) + :action 'element-with-markers + :narrow narrow + :sort sort))) + (->> (if (cdr queries) + (--map (rec (cdr queries) it (1+ indent)) + results) + results) + (-flatten-n (1- (length queries))) + -non-nil + (org-ql-agenda--agenda nil nil + :entries))))) + + (cl-defun org-ql-select-recursive (buffers-or-files queries &key action narrow sort) + (cl-labels ((rec (queries element indent) + (org-with-point-at (org-element-property :org-marker element) + (when-let* ((results (progn + (org-narrow-to-subtree) + (org-ql-select (current-buffer) + (car queries) + :action 'element-with-markers + :narrow t + :sort sort)))) + ;; Indent entry for each level + (setf results (--map + (org-element-put-property it :raw-value + (concat (s-repeat (* 5 indent) " ") + (org-element-property :raw-value it))) + results)) + (cons it (if (cdr queries) + (--map (rec (cdr queries) it) + results) + results)))))) + (when-let* ((indent 0) + (results (org-ql-select buffers-or-files + (car queries) + :action 'element-with-markers + :narrow narrow + :sort sort))) + (->> (if (cdr queries) + (--map (rec (cdr queries) it (1+ indent)) + results) + results) + (-flatten-n (1- (length queries))) + -non-nil)))) +#+END_SRC ** TODO [#B] Timeline view @@ -186,104 +446,6 @@ Another, more up-to-date implementation: ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") #+END_SRC -** TODO [#B] Add more sorters? - -+ [ ] =category= -+ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry - -** TODO [#B] Default sort - -Would probably be useful to have a default sort option. - -** TODO [#B] Normalize queries - -[2019-07-16 Tue 11:49] This serves two purposes: - -1. Equivalent queries will return the same results from the cache. -2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file. - -So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. - -** TODO [#B] Quickly change sorting/grouping in search views - -With caching, the search doesn't need to be repeated, so resorting/regrouping can be very fast. - -** TODO [#B] Recursive queries - -For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. - -This works pretty well. It needs polishing, and some refactoring so items can be indented completely (rather than leaving the keyword unindented, as it is now). - -#+BEGIN_SRC elisp - (cl-defun org-ql-agenda-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil - (org-ql-agenda--agenda nil nil - :entries))))) - - (cl-defun org-ql-select-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil)))) -#+END_SRC - ** TODO [#B] Timeline view :PROPERTIES: :ID: 00573552-ffe9-4608-8904-7f6c73246b6d @@ -363,137 +525,6 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or e.g. doesn't currently show the =View= header. -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** TODO [#C] ~org-agenda-skip-function~ - -As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: - -#+BEGIN_SRC elisp - ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- - - (defun org-ql-skip-function (query) - "Return a function for `org-agenda-skip-function' for QUERY. - Compared to using QUERY in `org-ql', this effectively turns QUERY - into (not QUERY)." - (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) - (lambda () - ;; This duplicates the functionality of `org-ql--select'. - (let (orig-fns) - (--each org-ql-predicates - ;; Save original function mappings. - (let ((name (plist-get it :name))) - (push (list :name name :fn (symbol-function name)) orig-fns))) - (unwind-protect - (progn - (--each org-ql-predicates - ;; Set predicate functions. - (fset (plist-get it :name) (plist-get it :fn))) - ;; Run query. - ;; FIXME: "If this function returns nil, the current match should not be skipped. - ;; Otherwise, the function must return a position from where the search - ;; should be continued." - (funcall predicate)) - (--each orig-fns - ;; Restore original function mappings. - (fset (plist-get it :name) (plist-get it :fn)))))))) - - (let ((org-agenda-custom-commands - '(("z" "Z" - ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) - ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) - ((org-agenda-files ("~/org/inbox.org")))))) - (org-agenda nil "z")) -#+END_SRC - -I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... - -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** TODO [#C] Update commentary - -** UNDERWAY [#A] Outline path predicate - -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: - -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. - -** UNDERWAY [#B] Implement view with tabulated-list-mode or magit-section - -[2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. - -[2019-09-08 Sun 10:06] Came up with a prototype yesterday, in branch =wip/view-section=. Seems to work pretty well. - -One of the things in that branch is =org-ql-item=, which is a struct used to carry data for query results. It seems to work well. - -Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. - -*** TODO Experiment with =widget= - -The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. - -*** Prior art - -**** magit-section - -**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] - -Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. - -*** Code idea - -Inserting items into a view could look something like this: - -#+BEGIN_SRC elisp - (org-ql-view--insert-items - :header (ts-format "%Y-%m-%d" (ts-now)) - :items (org-ql-query - :select #'org-ql-current-item - :from (org-agenda-files) - :where '(or (deadline auto) - (scheduled :on today) - (ts-active :on today))) - :group-by '(org-ql-item-priority - org-ql-item-todo)) -#+END_SRC - -Items would be structs, and the =group-by= argument would be a list of accessors, like how =magit-todos= works. Arbitrary functions could also be passed to =group-by=, as whatever value the function returns is used to group them. =org-ql-current-item= would be a function that turns the result of =org-element-headline-parser= into the struct. - -Not sure if it should automatically add the number of items to the header, or if that should be done manually. - ** UNDERWAY [#B] "Node" caching [2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. @@ -598,6 +629,49 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** UNDERWAY [#B] Implement view with tabulated-list-mode or magit-section + +[2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. + +[2019-09-08 Sun 10:06] Came up with a prototype yesterday, in branch =wip/view-section=. Seems to work pretty well. + +One of the things in that branch is =org-ql-item=, which is a struct used to carry data for query results. It seems to work well. + +Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. + +*** TODO Experiment with =widget= + +The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. + +*** Code idea + +Inserting items into a view could look something like this: + +#+BEGIN_SRC elisp + (org-ql-view--insert-items + :header (ts-format "%Y-%m-%d" (ts-now)) + :items (org-ql-query + :select #'org-ql-current-item + :from (org-agenda-files) + :where '(or (deadline auto) + (scheduled :on today) + (ts-active :on today))) + :group-by '(org-ql-item-priority + org-ql-item-todo)) +#+END_SRC + +Items would be structs, and the =group-by= argument would be a list of accessors, like how =magit-todos= works. Arbitrary functions could also be passed to =group-by=, as whatever value the function returns is used to group them. =org-ql-current-item= would be a function that turns the result of =org-element-headline-parser= into the struct. + +Not sure if it should automatically add the number of items to the header, or if that should be done manually. + +*** Prior art + +**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] + +Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. + +**** magit-section + ** MAYBE Fancier plain query syntax for tags and properties e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. @@ -617,133 +691,10 @@ Searching that with a query like =property:author=Fabrice= returns nothing; the [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. -** MAYBE [#C] Fancier searching for inherited tags - -When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. - ** MAYBE Use Bovine or Wisent to parse non-sexp syntax They're both built-in to Emacs, so we could drop the =peg= dependency. -** DONE [#A] Helm command - -In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. - -*** DONE Add - -*** DONE Demonstrate - -*** DONE Parsing non-Lisp queries - -[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror)) - ((predicate . args) (nreverse parsed))) - (when predicate - (list :predicate predicate :args args :combinator combinator))) - ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) -#+END_SRC - -I don't know where the =t= is coming from. - -The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (syntax-class whitespace)))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) -#+END_SRC - -In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. - -This seems to work, but we'll have to parse the args again in a separate step: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) -#+END_SRC - -Well, a bit of fiddling (lots of trial-and-error required) produced this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) -#+END_SRC - -That seems pretty usable! - ** DONE Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] :LOGBOOK: @@ -982,6 +933,63 @@ If I made the =date= selector a macro, I could avoid the need to quote the compa Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc. +** TODO [#C] ~org-agenda-skip-function~ + +As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: + +#+BEGIN_SRC elisp + ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- + + (defun org-ql-skip-function (query) + "Return a function for `org-agenda-skip-function' for QUERY. + Compared to using QUERY in `org-ql', this effectively turns QUERY + into (not QUERY)." + (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) + (lambda () + ;; This duplicates the functionality of `org-ql--select'. + (let (orig-fns) + (--each org-ql-predicates + ;; Save original function mappings. + (let ((name (plist-get it :name))) + (push (list :name name :fn (symbol-function name)) orig-fns))) + (unwind-protect + (progn + (--each org-ql-predicates + ;; Set predicate functions. + (fset (plist-get it :name) (plist-get it :fn))) + ;; Run query. + ;; FIXME: "If this function returns nil, the current match should not be skipped. + ;; Otherwise, the function must return a position from where the search + ;; should be continued." + (funcall predicate)) + (--each orig-fns + ;; Restore original function mappings. + (fset (plist-get it :name) (plist-get it :fn)))))))) + + (let ((org-agenda-custom-commands + '(("z" "Z" + ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) + ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) + ((org-agenda-files ("~/org/inbox.org")))))) + (org-agenda nil "z")) +#+END_SRC + +I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... + +** TODO [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + +** TODO [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + +** TODO [#C] Update commentary + +** MAYBE [#C] Fancier searching for inherited tags + +When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. + * References ** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] From ab5e9aa9116010e5da1995bf19ff26f55b93c214 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 26 Mar 2020 04:41:46 -0500 Subject: [PATCH 130/560] Notes: Add idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 9bd04d2..4cf5b39 100644 --- a/notes.org +++ b/notes.org @@ -525,6 +525,10 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or e.g. doesn't currently show the =View= header. +** TODO Dynamic blocks + +For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. + ** UNDERWAY [#B] "Node" caching [2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. From 81673fc7b599347e6fec0755caadb69fb5a2e430 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 7 Apr 2020 12:05:24 -0500 Subject: [PATCH 131/560] Fix: (org-ql-predicates) Use eval-and-compile This is technically correct, even though package.el might obscure the problem by causing the file to be loaded before it is compiled. --- org-ql.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/org-ql.el b/org-ql.el index a03f6d6..43e5237 100644 --- a/org-ql.el +++ b/org-ql.el @@ -123,10 +123,11 @@ tick, and another hash table keyed on buffer position, whose values are alists in which the key is a function and the value is the value returned by it at that node.") -(defvar org-ql-predicates - (list (list :name 'org-back-to-heading :fn (symbol-function 'org-back-to-heading))) - "Plist of predicates, their corresponding functions, and their docstrings. -This list should not contain any duplicates.") +(eval-and-compile + (defvar org-ql-predicates + (list (list :name 'org-back-to-heading :fn (symbol-function 'org-back-to-heading))) + "Plist of predicates, their corresponding functions, and their docstrings. +This list should not contain any duplicates.")) ;;;; Customization From f4d7399e677904cdc7e220440610704e4bd668bc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 7 Apr 2020 12:06:57 -0500 Subject: [PATCH 132/560] Fix: (org-ql-view--contract-buffers-files) Only compare to function If the org-agenda-files variable points to a file pointing to a list of agenda files, it shouldn't be compared to. We should only compare to the value returned by the org-agenda-files function. Fixes #104. Thanks to @gdindi for reporting. --- org-ql-view.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index d6cd536..7739ea7 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -841,14 +841,14 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." list))) ;; TODO: Test this more exhaustively. (pcase buffers-files - ((pred listp) (pcase (expand-files buffers-files) - ((or (pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) - (pred (seq-set-equal-p (mapcar #'expand-file-name org-agenda-files)))) - "org-agenda-files") - ((pred (seq-set-equal-p (org-ql-search-directories-files))) - "org-directory") - (_ (let ((print-length nil)) - (concat "'" (prin1-to-string buffers-files)))))) + ((pred listp) + (pcase (expand-files buffers-files) + ((pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) + "org-agenda-files") + ((pred (seq-set-equal-p (org-ql-search-directories-files))) + "org-directory") + (_ (let ((print-length nil)) + (concat "'" (prin1-to-string buffers-files)))))) ((pred (equal (current-buffer))) "buffer") ((or 'org-agenda-files '(function org-agenda-files)) From 5a031bf5c19d274934f80d616d6fde62a6db5786 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 1 May 2020 06:20:46 -0500 Subject: [PATCH 133/560] Fix: (org-ql--select) Bind case-fold-search only around preamble Fixes #114. Thanks to @bitclick for reporting. Released as 0.4.5. --- README.org | 5 ++ org-ql.el | 14 ++--- org-ql.info | 124 ++++++++++++++++++++++++------------------- tests/test-org-ql.el | 7 +++ 4 files changed, 89 insertions(+), 61 deletions(-) diff --git a/README.org b/README.org index d6e654b..b272b15 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.5 + +*Fixed* ++ Non-case-folding predicates like ~(todo)~ unnecessarily disabled case-folding for other predicates. ([[https://github.com/alphapapa/org-ql/issues/114][Issue #114]]. Thanks to [[https://github.com/bitclick][@bitclick]] for reporting.) + ** 0.4.4 *Fixed* diff --git a/org-ql.el b/org-ql.el index aef1854..0307d78 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.4 +;; Version: 0.4.5 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda @@ -355,12 +355,12 @@ If NARROW is non-nil, buffer will not be widened." (message "org-ql: No headings in buffer: %s" (current-buffer))) nil) ;; Find matching entries. - (cond (preamble (let ((case-fold-search preamble-case-fold)) - (cl-loop while (re-search-forward preamble nil t) - do (outline-back-to-heading 'invisible-ok) - when (funcall predicate) - collect (funcall action) - do (outline-next-heading)))) + (cond (preamble (cl-loop while (let ((case-fold-search preamble-case-fold)) + (re-search-forward preamble nil t)) + do (outline-back-to-heading 'invisible-ok) + when (funcall predicate) + collect (funcall action) + do (outline-next-heading))) (t (cl-loop when (funcall predicate) collect (funcall action) while (outline-next-heading)))))))) diff --git a/org-ql.info b/org-ql.info index 5919d5e..b5d86ef 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.5: 045. * 0.4.4: 044. * 0.4.3: 043. * 0.4.2: 042. @@ -151,7 +152,8 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top 4 Usage ******* - • • • • + • • + • • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -706,6 +708,7 @@ releases. * Menu: +* 0.4.5: 045. * 0.4.4: 044. * 0.4.3: 043. * 0.4.2: 042. @@ -721,9 +724,21 @@ releases. * 0.1: 01.  -File: README.info, Node: 044, Next: 043, Up: Changelog +File: README.info, Node: 045, Next: 044, Up: Changelog -5.1 0.4.4 +5.1 0.4.5 +========= + +*Fixed* + • Non-case-folding predicates like ‘(todo)’ unnecessarily disabled + case-folding for other predicates. (Issue #114 + (https://github.com/alphapapa/org-ql/issues/114). Thanks to + @bitclick (https://github.com/bitclick) for reporting.) + + +File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog + +5.2 0.4.4 ========= *Fixed* @@ -735,7 +750,7 @@ File: README.info, Node: 044, Next: 043, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.2 0.4.3 +5.3 0.4.3 ========= *Fixed* @@ -745,7 +760,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.3 0.4.2 +5.4 0.4.2 ========= *Fixed* @@ -754,7 +769,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.4 0.4.1 +5.5 0.4.1 ========= *Fixed* @@ -764,7 +779,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.5 0.4 +5.6 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -845,7 +860,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.6 0.3.2 +5.7 0.3.2 ========= *Fixed* @@ -858,7 +873,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.7 0.3.1 +5.8 0.3.1 ========= *Fixed* @@ -868,7 +883,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.8 0.3 +5.9 0.3 ======= *Added* @@ -933,8 +948,8 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.9 0.2.3 -========= +5.10 0.2.3 +========== *Fixed* • Priority queries could fail to match headings whose to-do keywords @@ -943,7 +958,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.10 0.2.2 +5.11 0.2.2 ========== *Fixed* @@ -954,7 +969,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.11 0.2.1 +5.12 0.2.1 ========== *Fixed* @@ -964,7 +979,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.12 0.2 +5.13 0.2 ======== *Added* @@ -1047,7 +1062,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.13 0.1 +5.14 0.1 ======== First tagged release. @@ -1108,44 +1123,45 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1462 -Node: Screenshots1636 -Node: Installation1754 -Node: Quelpa2392 -Node: Usage2835 -Node: Commands3163 -Node: org-ql-search3636 -Node: helm-org-ql5284 -Node: org-ql-view5696 -Node: org-ql-view-sidebar5894 -Node: org-ql-view-recent-items6250 -Node: org-ql-sparse-tree6734 -Node: Queries7534 -Node: Non-sexp query syntax8442 -Node: General predicates10149 -Node: Ancestor/descendant predicates14956 -Node: Date/time predicates16084 -Node: Functions / Macros18739 -Node: Agenda-like views18972 -Node: Listing / acting-on results20377 -Node: Changelog24979 -Node: 04425568 -Node: 04325913 -Node: 04226108 -Node: 04126267 -Node: 0426506 -Node: 03230437 -Node: 03130814 -Node: 0331009 -Node: 02333982 -Node: 02234208 -Node: 02134476 -Node: 0234675 -Node: 0138710 -Node: Notes38811 -Node: Comparison with Org Agenda searches38973 -Node: org-sidebar39844 -Node: License40123 +Node: Contents1477 +Node: Screenshots1651 +Node: Installation1769 +Node: Quelpa2407 +Node: Usage2850 +Node: Commands3199 +Node: org-ql-search3672 +Node: helm-org-ql5320 +Node: org-ql-view5732 +Node: org-ql-view-sidebar5930 +Node: org-ql-view-recent-items6286 +Node: org-ql-sparse-tree6770 +Node: Queries7570 +Node: Non-sexp query syntax8478 +Node: General predicates10185 +Node: Ancestor/descendant predicates14992 +Node: Date/time predicates16120 +Node: Functions / Macros18775 +Node: Agenda-like views19008 +Node: Listing / acting-on results20413 +Node: Changelog25015 +Node: 04525619 +Node: 04425966 +Node: 04326323 +Node: 04226518 +Node: 04126677 +Node: 0426916 +Node: 03230847 +Node: 03131224 +Node: 0331419 +Node: 02334392 +Node: 02234620 +Node: 02134888 +Node: 0235087 +Node: 0139122 +Node: Notes39223 +Node: Comparison with Org Agenda searches39385 +Node: org-sidebar40256 +Node: License40535  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index bf2340f..71c3ecf 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -707,6 +707,13 @@ RESULTS should be a list of strings as returned by (org-ql-it "with two plain strings in an OR" (org-ql-expect ((or "Take over" "universe") :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + + (org-ql-it "case-folding predicate with non-case-folding preamble" + ;; e.g. the (todo) predicate disables case-folding in its preamble, but that + ;; should not prevent case-folding in this and other predicates (issue #114). + (org-ql-expect ((and (todo "TODO") (regexp "take over")) + :sort todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) (describe "(scheduled)" From 00800556907408ee11a23de3a4982061d08d3b85 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 12 Jul 2020 21:54:59 -0500 Subject: [PATCH 134/560] Fix: Copy macro peg-parse-string from peg-tests.el Unfortunately, the macro was moved from peg.el to peg-tests.el in later versions of peg, so we copy it for our use here. Fixes #75. Thanks to Karl Voit (@novoid) and @karlicoss for reporting. Released as 0.4.6. --- README.org | 5 +++ org-ql.el | 19 +++++++- org-ql.info | 126 +++++++++++++++++++++++++++++----------------------- 3 files changed, 93 insertions(+), 57 deletions(-) diff --git a/README.org b/README.org index b272b15..a7d79eb 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.6 + +*Fixed* ++ Compatibility with newer versions of the =peg= library, which removed a macro used by this package. (Fixes [[https://github.com/alphapapa/org-ql/issues/75][#75]]. Thanks to [[https://github.com/novoid][Karl Voit]] and [[https://github.com/karlicoss][@karlicoss]] for reporting.) + ** 0.4.5 *Fixed* diff --git a/org-ql.el b/org-ql.el index 0307d78..f7efbbf 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.5 +;; Version: 0.4.6 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda @@ -1529,6 +1529,21 @@ element should be a regexp string." (defvar peg-errors nil) (defvar peg-stack nil) +(defmacro org-ql--peg-parse-string (rules string &optional noerror) + "Parse STRING according to RULES. +If NOERROR is non-nil, push nil resp. t if the parse failed +resp. succeded instead of signaling an error." + ;; Unfortunately, this macro was moved to peg-tests.el, so we copy it here. + `(with-temp-buffer + (insert ,string) + (goto-char (point-min)) + ,(if noerror + (let ((entry (make-symbol "entry")) + (start (caar rules))) + `(peg-parse (entry (or (and ,start `(-- t)) "")) + . ,rules)) + `(peg-parse . ,rules)))) + (cl-eval-when (compile load eval) ;; This `eval-when' is necessary, otherwise the macro does not define ;; the function correctly, apparently because `org-ql-predicates' @@ -1555,7 +1570,7 @@ Builds the PEG expression using predicates defined in "Return query parsed from plain query string INPUT. Multiple predicates are combined with BOOLEAN." (unless (s-blank-str? input) - (let* ((query (peg-parse-string + (let* ((query (org-ql--peg-parse-string ((query (+ term (opt (+ (syntax-class whitespace) (any))))) (term (or (and negation (list positive-term) diff --git a/org-ql.info b/org-ql.info index b5d86ef..213b610 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.6: 046. * 0.4.5: 045. * 0.4.4: 044. * 0.4.3: 043. @@ -708,6 +709,7 @@ releases. * Menu: +* 0.4.6: 046. * 0.4.5: 045. * 0.4.4: 044. * 0.4.3: 043. @@ -724,9 +726,22 @@ releases. * 0.1: 01.  -File: README.info, Node: 045, Next: 044, Up: Changelog +File: README.info, Node: 046, Next: 045, Up: Changelog -5.1 0.4.5 +5.1 0.4.6 +========= + +*Fixed* + • Compatibility with newer versions of the peg library, which removed + a macro used by this package. (Fixes #75 + (https://github.com/alphapapa/org-ql/issues/75). Thanks to Karl + Voit (https://github.com/novoid) and @karlicoss + (https://github.com/karlicoss) for reporting.) + + +File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog + +5.2 0.4.5 ========= *Fixed* @@ -738,7 +753,7 @@ File: README.info, Node: 045, Next: 044, Up: Changelog  File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog -5.2 0.4.4 +5.3 0.4.4 ========= *Fixed* @@ -750,7 +765,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.3 0.4.3 +5.4 0.4.3 ========= *Fixed* @@ -760,7 +775,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.4 0.4.2 +5.5 0.4.2 ========= *Fixed* @@ -769,7 +784,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.5 0.4.1 +5.6 0.4.1 ========= *Fixed* @@ -779,7 +794,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.6 0.4 +5.7 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -860,7 +875,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.7 0.3.2 +5.8 0.3.2 ========= *Fixed* @@ -873,7 +888,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.8 0.3.1 +5.9 0.3.1 ========= *Fixed* @@ -883,8 +898,8 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.9 0.3 -======= +5.10 0.3 +======== *Added* • Alternative, non-sexp query syntax for commands org-ql-search and @@ -948,7 +963,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.10 0.2.3 +5.11 0.2.3 ========== *Fixed* @@ -958,7 +973,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.11 0.2.2 +5.12 0.2.2 ========== *Fixed* @@ -969,7 +984,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.12 0.2.1 +5.13 0.2.1 ========== *Fixed* @@ -979,7 +994,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.13 0.2 +5.14 0.2 ======== *Added* @@ -1062,7 +1077,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.14 0.1 +5.15 0.1 ======== First tagged release. @@ -1123,45 +1138,46 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1477 -Node: Screenshots1651 -Node: Installation1769 -Node: Quelpa2407 -Node: Usage2850 -Node: Commands3199 -Node: org-ql-search3672 -Node: helm-org-ql5320 -Node: org-ql-view5732 -Node: org-ql-view-sidebar5930 -Node: org-ql-view-recent-items6286 -Node: org-ql-sparse-tree6770 -Node: Queries7570 -Node: Non-sexp query syntax8478 -Node: General predicates10185 -Node: Ancestor/descendant predicates14992 -Node: Date/time predicates16120 -Node: Functions / Macros18775 -Node: Agenda-like views19008 -Node: Listing / acting-on results20413 -Node: Changelog25015 -Node: 04525619 -Node: 04425966 -Node: 04326323 -Node: 04226518 -Node: 04126677 -Node: 0426916 -Node: 03230847 -Node: 03131224 -Node: 0331419 -Node: 02334392 -Node: 02234620 -Node: 02134888 -Node: 0235087 -Node: 0139122 -Node: Notes39223 -Node: Comparison with Org Agenda searches39385 -Node: org-sidebar40256 -Node: License40535 +Node: Contents1492 +Node: Screenshots1666 +Node: Installation1784 +Node: Quelpa2422 +Node: Usage2865 +Node: Commands3214 +Node: org-ql-search3687 +Node: helm-org-ql5335 +Node: org-ql-view5747 +Node: org-ql-view-sidebar5945 +Node: org-ql-view-recent-items6301 +Node: org-ql-sparse-tree6785 +Node: Queries7585 +Node: Non-sexp query syntax8493 +Node: General predicates10200 +Node: Ancestor/descendant predicates15007 +Node: Date/time predicates16135 +Node: Functions / Macros18790 +Node: Agenda-like views19023 +Node: Listing / acting-on results20428 +Node: Changelog25030 +Node: 04625649 +Node: 04526037 +Node: 04426396 +Node: 04326753 +Node: 04226948 +Node: 04127107 +Node: 0427346 +Node: 03231277 +Node: 03131654 +Node: 0331849 +Node: 02334824 +Node: 02235052 +Node: 02135320 +Node: 0235519 +Node: 0139554 +Node: Notes39655 +Node: Comparison with Org Agenda searches39817 +Node: org-sidebar40688 +Node: License40967  End Tag Table From 65cc3fc24e10c10e2b667b3a3a629317bae410c3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 19 Oct 2020 00:23:50 -0500 Subject: [PATCH 135/560] Notes: Add task --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 4cf5b39..3aa42dd 100644 --- a/notes.org +++ b/notes.org @@ -2,6 +2,10 @@ * Tasks +** TODO [#B] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] + +[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. + ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. From 57708e6cc1ee8d7fc4a4d5876e2f600d5b8466f1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Nov 2020 20:12:31 -0600 Subject: [PATCH 136/560] Change: (-view--plist, -view-save) Factor out plist code In preparation for bookmark support. --- org-ql-view.el | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 7739ea7..15499a3 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -343,12 +343,10 @@ update search arguments." "Save current `org-ql-search' buffer to `org-ql-views'." (interactive) (let* ((name (read-string "Save view as: " org-ql-view-title)) - (plist (list :buffers-files org-ql-view-buffers-files - :query org-ql-view-query - :sort org-ql-view-sort - :narrow org-ql-view-narrow - :super-groups org-ql-view-super-groups - :title name))) + ;; Bind `org-ql-view-title' to the name that was read, in case + ;; it's different, which `org-ql-view--plist' will pick up. + (org-ql-view-title name) + (plist (org-ql-view--plist (current-buffer)))) (when (or (not (map-elt org-ql-views name nil)) (yes-or-no-p (format "Overwrite view \"%s\"?" name))) (setf (map-elt org-ql-views name nil #'equal) plist) @@ -374,6 +372,16 @@ update search arguments." ;;;; Functions +(defun org-ql-view--plist (buffer) + "Return plist describing Org QL View in BUFFER." + (with-current-buffer buffer + (list :buffers-files org-ql-view-buffers-files + :query org-ql-view-query + :sort org-ql-view-sort + :narrow org-ql-view-narrow + :super-groups org-ql-view-super-groups + :title org-ql-view-title))) + (defun org-ql-view--list-buffer () "Return view list buffer." (with-current-buffer (get-buffer-create "*Org QL View List*") From e5b4cd106558790563af26a8e32ec9508f904855 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Nov 2020 20:14:43 -0600 Subject: [PATCH 137/560] Add: Bookmark support --- README.org | 1 + org-ql-view.el | 35 +++++++++++++++++++++++++++++++++++ org-ql.info | 42 +++++++++++++++++++++++------------------- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/README.org b/README.org index fdc43fc..842a50a 100644 --- a/README.org +++ b/README.org @@ -407,6 +407,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Added* + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. + Predicate =link=, which matches descriptions and targets in Org links. ++ Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) + Mascot. *Changed* diff --git a/org-ql-view.el b/org-ql-view.el index 15499a3..9e69b62 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -428,6 +428,7 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', (null (org-ql-view--buffer buffer)) (buffer buffer)))) (with-current-buffer buffer + (setq-local bookmark-make-record-function #'org-ql-view--bookmark-make-record) (use-local-map org-ql-view-map) ;; Prepare buffer, saving data for refreshing. (cl-loop for symbol in vars @@ -519,6 +520,40 @@ dates in the past, and negative for dates in the future." (format "in %sd" (* -1 difference))) (t "today"))) +;;;; Bookmarks + +;; Support for Emacs bookmarks. + +(eval-when-compile + (require 'bookmark)) + +(defun org-ql-view--bookmark-make-record () + "Return a bookmark record for the current Org QL View buffer." + (list (concat "Org QL View: " org-ql-view-title) + (cons 'org-ql-view-plist (org-ql-view--plist (current-buffer))) + (cons 'handler #'org-ql-view--bookmark-handler) + (cons 'position (point)))) + +;;;###autoload +(defun org-ql-view--bookmark-handler (bookmark) + "Show Org QL View BOOKMARK in current buffer." + (pcase-let* (((map org-ql-view-plist) (bookmark-get-bookmark-record bookmark)) + ((map :buffers-files :query :super-groups :narrow :sort :title) + org-ql-view-plist) + (super-groups (cl-etypecase super-groups + (symbol (symbol-value super-groups)) + (list super-groups)))) + (org-ql-search buffers-files query + :super-groups super-groups :narrow narrow :sort sort :title title) + ;; HACK: `bookmark--jump-via' expects that, when the handler returns, the current buffer + ;; (not merely the selected window's buffer) is the one to be displayed. However, + ;; `org-ql-view--display' uses `with-current-buffer', which resets the current buffer to + ;; the one that was active when the bookmark was jumped to. So we set the buffer before + ;; returning. It might be better to refactor `org-ql-view--display' into a function that + ;; returns a buffer which can be displayed by the calling function. But that would be + ;; more complicated and might introduce bugs elsewhere, so we'll just do this for now. + (set-buffer (window-buffer (selected-window))))) + ;;;; Transient ;; This section uses `transient' to allow the user to easily modify diff --git a/org-ql.info b/org-ql.info index 1791312..55c0d52 100644 --- a/org-ql.info +++ b/org-ql.info @@ -750,6 +750,10 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog search/view buffers. • Predicate link, which matches descriptions and targets in Org links. + • Emacs bookmark support: Org QL View buffers can be bookmarked with, + e.g. C-x r m and shown with, e.g. C-x r b. (This also enables + view restoration with Burly + (https://github.com/alphapapa/burly.el).) • Mascot. *Changed* @@ -1187,25 +1191,25 @@ Node: Agenda-like views19768 Node: Listing / acting-on results21173 Node: Changelog25775 Node: 05-pre26414 -Node: 04626778 -Node: 04527181 -Node: 04427540 -Node: 04327897 -Node: 04228092 -Node: 04128251 -Node: 0428490 -Node: 03232421 -Node: 03132798 -Node: 0332995 -Node: 02335970 -Node: 02236198 -Node: 02136466 -Node: 0236665 -Node: 0140700 -Node: Notes40801 -Node: Comparison with Org Agenda searches40963 -Node: org-sidebar41835 -Node: License42114 +Node: 04627003 +Node: 04527406 +Node: 04427765 +Node: 04328122 +Node: 04228317 +Node: 04128476 +Node: 0428715 +Node: 03232646 +Node: 03133023 +Node: 0333220 +Node: 02336195 +Node: 02236423 +Node: 02136691 +Node: 0236890 +Node: 0140925 +Node: Notes41026 +Node: Comparison with Org Agenda searches41188 +Node: org-sidebar42060 +Node: License42339  End Tag Table From 028c25c1061fd56d7c739c7a66f3059534a92524 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 2 Nov 2020 21:35:42 -0600 Subject: [PATCH 138/560] Fix: (-view--bookmark-make-record) Replace buffers with filenames --- org-ql-view.el | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 9e69b62..e44cfbd 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -529,10 +529,24 @@ dates in the past, and negative for dates in the future." (defun org-ql-view--bookmark-make-record () "Return a bookmark record for the current Org QL View buffer." - (list (concat "Org QL View: " org-ql-view-title) - (cons 'org-ql-view-plist (org-ql-view--plist (current-buffer))) - (cons 'handler #'org-ql-view--bookmark-handler) - (cons 'position (point)))) + (cl-labels ((file-nameize + (b-f) (or (buffer-file-name b-f) + (when (buffer-base-buffer b-f) + (buffer-file-name (buffer-base-buffer b-f))) + (user-error "Only file-backed buffers can be bookmarked by Org QL View: %s" b-f)))) + (pcase-let* ((plist (org-ql-view--plist (current-buffer))) + ((map :buffers-files) plist)) + ;; Replace buffers with their filenames, and signal error if any are not file-backed. + (setf plist (plist-put plist :buffers-files + (cl-etypecase buffers-files + (string buffers-files) + (buffer (file-nameize buffers-files)) + (list (cl-loop for b-f in buffers-files + collect (file-nameize b-f)))))) + (list (concat "Org QL View: " org-ql-view-title) + (cons 'org-ql-view-plist plist) + (cons 'handler #'org-ql-view--bookmark-handler) + (cons 'position (point)))))) ;;;###autoload (defun org-ql-view--bookmark-handler (bookmark) From f88fb549a39174494a49ebd162057fa17fdd6849 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 5 Nov 2020 11:21:06 -0600 Subject: [PATCH 139/560] Docs: Add Tips section --- README.org | 5 +++ org-ql.info | 100 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 62 insertions(+), 43 deletions(-) diff --git a/README.org b/README.org index 842a50a..87416db 100644 --- a/README.org +++ b/README.org @@ -68,6 +68,7 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: - [[#ancestordescendant-predicates][Ancestor/descendant predicates]] - [[#datetime-predicates][Date/time predicates]] - [[#functions--macros][Functions / Macros]] +- [[#tips][Tips]] :END: # These links work on GitHub's Org renderer but not in Org. @@ -395,6 +396,10 @@ Examples: Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted. +** Tips + ++ Org QL View buffers can be bookmarked with Emacs bookmark commands, e.g. =C-x r m=. This also integrates with [[https://github.com/alphapapa/org-sidebar][org-sidebar]] and [[https://github.com/alphapapa/burly.el][Burly]]. + * Changelog :PROPERTIES: :TOC: ignore-children diff --git a/org-ql.info b/org-ql.info index 55c0d52..983eabb 100644 --- a/org-ql.info +++ b/org-ql.info @@ -35,6 +35,7 @@ Usage * Commands:: * Queries:: * Functions / Macros:: +* Tips:: Commands @@ -153,7 +154,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top ******* • • - • • • • • + • • • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -164,6 +165,7 @@ and polished, they will be considered stable. * Commands:: * Queries:: * Functions / Macros:: +* Tips::  File: README.info, Node: Commands, Next: Queries, Up: Usage @@ -542,7 +544,7 @@ number of days. The number can be negative to invert the direction. scheduled at any time.  -File: README.info, Node: Functions / Macros, Prev: Queries, Up: Usage +File: README.info, Node: Functions / Macros, Next: Tips, Prev: Queries, Up: Usage 4.3 Functions / Macros ====================== @@ -708,6 +710,17 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, Expands into a call to ‘org-ql-select’ with the same arguments. For convenience, arguments should be unquoted. + +File: README.info, Node: Tips, Prev: Functions / Macros, Up: Usage + +4.4 Tips +======== + + • Org QL View buffers can be bookmarked with Emacs bookmark commands, + e.g. C-x r m. This also integrates with org-sidebar + (https://github.com/alphapapa/org-sidebar) and Burly + (https://github.com/alphapapa/burly.el). +  File: README.info, Node: Changelog, Next: Notes, Prev: Usage, Up: Top @@ -1169,47 +1182,48 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1512 -Node: Screenshots1635 -Node: Installation1753 -Node: Quelpa2391 -Node: Usage2834 -Node: Commands3183 -Node: org-ql-search3656 -Node: helm-org-ql5370 -Node: org-ql-view5782 -Node: org-ql-view-sidebar6282 -Node: org-ql-view-recent-items6638 -Node: org-ql-sparse-tree7122 -Node: Queries7922 -Node: Non-sexp query syntax8830 -Node: General predicates10537 -Node: Ancestor/descendant predicates15752 -Node: Date/time predicates16880 -Node: Functions / Macros19535 -Node: Agenda-like views19768 -Node: Listing / acting-on results21173 -Node: Changelog25775 -Node: 05-pre26414 -Node: 04627003 -Node: 04527406 -Node: 04427765 -Node: 04328122 -Node: 04228317 -Node: 04128476 -Node: 0428715 -Node: 03232646 -Node: 03133023 -Node: 0333220 -Node: 02336195 -Node: 02236423 -Node: 02136691 -Node: 0236890 -Node: 0140925 -Node: Notes41026 -Node: Comparison with Org Agenda searches41188 -Node: org-sidebar42060 -Node: License42339 +Node: Contents1521 +Node: Screenshots1644 +Node: Installation1762 +Node: Quelpa2400 +Node: Usage2843 +Node: Commands3205 +Node: org-ql-search3678 +Node: helm-org-ql5392 +Node: org-ql-view5804 +Node: org-ql-view-sidebar6304 +Node: org-ql-view-recent-items6660 +Node: org-ql-sparse-tree7144 +Node: Queries7944 +Node: Non-sexp query syntax8852 +Node: General predicates10559 +Node: Ancestor/descendant predicates15774 +Node: Date/time predicates16902 +Node: Functions / Macros19557 +Node: Agenda-like views19803 +Node: Listing / acting-on results21208 +Node: Tips25810 +Node: Changelog26141 +Node: 05-pre26780 +Node: 04627369 +Node: 04527772 +Node: 04428131 +Node: 04328488 +Node: 04228683 +Node: 04128842 +Node: 0429081 +Node: 03233012 +Node: 03133389 +Node: 0333586 +Node: 02336561 +Node: 02236789 +Node: 02137057 +Node: 0237256 +Node: 0141291 +Node: Notes41392 +Node: Comparison with Org Agenda searches41554 +Node: org-sidebar42426 +Node: License42705  End Tag Table From 94be07244c3257c695dca351e090dc01d13eef01 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 5 Nov 2020 11:21:33 -0600 Subject: [PATCH 140/560] Fix: (org-ql-view-refresh) Rename buffer uniquely This is sort of a workaround or preventative measure as much as it is a fix. It seemed to be necessary when I was testing bookmark loading in org-sidebar. --- org-ql-view.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index e44cfbd..d5f3935 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -332,7 +332,9 @@ update search arguments." ;; Now in the results buffer. (rename-buffer (format "%s %s*" org-ql-view-buffer-name-prefix - (or org-ql-view-title org-ql-view-query))) + (or org-ql-view-title org-ql-view-query)) + ;; Avoid any errors in case a buffer by this name already exists. + 'unique) (goto-char (point-min)) (or (when (search-forward current-line nil t) (beginning-of-line)) From 5e61d1b326e3ecc16cc5ef974226697039f937fe Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 5 Nov 2020 11:28:22 -0600 Subject: [PATCH 141/560] Fix: (org-ql--peg-parse-string) Unused lexical variable warning peg.el doesn't use lexical binding, and org-ql.el does, so this caused a byte-compile warning. It doesn't seem to change the behavior of the expanded code, so it should be a safe change... --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 4196ab4..4e4e5fd 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1682,7 +1682,7 @@ resp. succeded instead of signaling an error." ,(if noerror (let ((entry (make-symbol "entry")) (start (caar rules))) - `(peg-parse (entry (or (and ,start `(-- t)) "")) + `(peg-parse (,entry (or (and ,start `(-- t)) "")) . ,rules)) `(peg-parse . ,rules)))) From 958cd5079447ba314baecb8429042942ff1b155e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Nov 2020 18:02:53 -0600 Subject: [PATCH 142/560] Meta: Update makem.sh --- makem.sh | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/makem.sh b/makem.sh index 91c3000..d110e2c 100755 --- a/makem.sh +++ b/makem.sh @@ -397,6 +397,27 @@ function ert-tests-p { grep "(ert-deftest" "${files_project_test[@]}" &>/dev/null } +function package-main-file { + # Echo the package's main file. Helpful for setting package-lint-main-file. + + file_pkg=$(git ls-files ./*-pkg.el 2>/dev/null) + + if [[ $file_pkg ]] + then + # Use *-pkg.el file if it exists. + echo "$file_pkg" + else + # Use shortest filename (a sloppy heuristic that will do for now). + for file in "${files_project_feature[@]}" + do + echo ${#file} "$file" + done \ + | sort -h \ + | head -n1 \ + | sed -r 's/^[[:digit:]]+ //' + fi +} + function dependencies { # Echo list of package dependencies. @@ -781,6 +802,7 @@ function lint-package { run_emacs \ --load package-lint \ + --eval "(setq package-lint-main-file \"$(package-main-file)\")" \ --funcall package-lint-batch-and-exit \ "${files_project_feature[@]}" \ && success "Linting package finished without errors." \ @@ -1022,6 +1044,7 @@ debug "EXCLUDING FILES: ${files_exclude[@]}" debug "FEATURE FILES: ${files_project_feature[@]}" debug "TEST FILES: ${files_project_test[@]}" debug "BYTE-COMPILE FILES: ${files_project_byte_compile[@]}" +debug "PACKAGE-MAIN-FILE: $(package-main-file)" if ! [[ ${files_project_feature[@]} ]] then From 359a280d11d54c940125f11d7be6a93f8c0c1095 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Nov 2020 18:05:27 -0600 Subject: [PATCH 143/560] Change/Fix: (org-ql-view--format-element) Use org-ql--tags-at Use org-ql--tags-at instead of org-get-tags/org-get-tags-at. This uses our cache, which should improve performance, and it obviates the function alias for Org versions before 9.3 (which occasionally misbehaves, e.g. if Org is reloaded). --- README.org | 3 +++ org-ql-view.el | 19 ++++++------------- org-ql.info | 44 +++++++++++++++++++++++++------------------- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/README.org b/README.org index 87416db..605b7bc 100644 --- a/README.org +++ b/README.org @@ -418,6 +418,9 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Changed* + Binding to refresh search/view buffers changed to =r=. +*Internal* ++ When formatting entries for Org QL View buffers, use internal function for retrieving heading tags. This improves speed by using our cache, and it removes the need for a compatibility alias for Org versions before 9.3. + ** 0.4.6 *Fixed* diff --git a/org-ql-view.el b/org-ql-view.el index d5f3935..30be96d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -47,11 +47,6 @@ (require 'ov) (require 'ts) -;;;; Compatibility - -(when (version< org-version "9.2") - (defalias 'org-get-tags #'org-get-tags-at)) - ;;;; Faces (defface org-ql-view-due-date @@ -729,18 +724,16 @@ return an empty string." (org-link-display-format it))) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-ql-view--add-todo-face it))) - ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. (tag-list (if org-use-tag-inheritance - ;; FIXME: Note that tag inheritance cannot be used here unless markers are - ;; added, otherwise we can't go to the item's buffer to look for inherited - ;; tags. (Or does `org-element-headline-parser' parse inherited tags too? I - ;; forget...) + ;; MAYBE: Use our own variable instead of `org-use-tag-inheritance'. (if-let ((marker (or (org-element-property :org-hd-marker element) (org-element-property :org-marker element)))) - (with-current-buffer (marker-buffer marker) - ;; I wish `org-get-tags' used the correct buffer automatically. - (org-get-tags marker (not org-use-tag-inheritance))) + (cl-loop for type in (org-ql--tags-at marker) + unless (or (eq 'org-ql-nil type) + (not type)) + append type) ;; No marker found + ;; TODO: Use `display-warning' with `org-ql' as the type. (warn "No marker found for item: %s" title) (org-element-property :tags element)) (org-element-property :tags element))) diff --git a/org-ql.info b/org-ql.info index 983eabb..fea110e 100644 --- a/org-ql.info +++ b/org-ql.info @@ -772,6 +772,12 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog *Changed* • Binding to refresh search/view buffers changed to r. + *Internal* + • When formatting entries for Org QL View buffers, use internal + function for retrieving heading tags. This improves speed by using + our cache, and it removes the need for a compatibility alias for + Org versions before 9.3. +  File: README.info, Node: 046, Next: 045, Prev: 05-pre, Up: Changelog @@ -1205,25 +1211,25 @@ Node: Listing / acting-on results21208 Node: Tips25810 Node: Changelog26141 Node: 05-pre26780 -Node: 04627369 -Node: 04527772 -Node: 04428131 -Node: 04328488 -Node: 04228683 -Node: 04128842 -Node: 0429081 -Node: 03233012 -Node: 03133389 -Node: 0333586 -Node: 02336561 -Node: 02236789 -Node: 02137057 -Node: 0237256 -Node: 0141291 -Node: Notes41392 -Node: Comparison with Org Agenda searches41554 -Node: org-sidebar42426 -Node: License42705 +Node: 04627626 +Node: 04528029 +Node: 04428388 +Node: 04328745 +Node: 04228940 +Node: 04129099 +Node: 0429338 +Node: 03233269 +Node: 03133646 +Node: 0333843 +Node: 02336818 +Node: 02237046 +Node: 02137314 +Node: 0237513 +Node: 0141548 +Node: Notes41649 +Node: Comparison with Org Agenda searches41811 +Node: org-sidebar42683 +Node: License42962  End Tag Table From 4194456b4023bba31fe6b8a43a1332cacbc3ce5d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Nov 2020 20:00:58 -0600 Subject: [PATCH 144/560] Notes: Update, add ToC, sort, etc. --- notes.org | 2726 +++++++++++++++++++++++++++-------------------------- 1 file changed, 1380 insertions(+), 1346 deletions(-) diff --git a/notes.org b/notes.org index 3aa42dd..5a9306b 100644 --- a/notes.org +++ b/notes.org @@ -1,10 +1,56 @@ #+PROPERTY: LOGGING nil -* Tasks +* [#A] Contents +:PROPERTIES: +:TOC: :include siblings :depth 1 :ignore this :force depth +:END: +:CONTENTS: +- [[#tasks][Tasks]] +- [[#examples--testing][Examples / testing]] +- [[#in-the-wild][In the wild]] +- [[#profiling][Profiling]] +- [[#references][References]] +- [[#testing][Testing]] +:END: -** TODO [#B] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] -[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. +* [#A] Tasks +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: +:CONTENTS: +- [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] +- [[#document-sorters][Document sorters]] +- [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] +- [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] +- [[#tools-for-saving-queries-and-accessing-them-24][Tools for saving queries and accessing them {2/4}]] +- [[#add-more-sorters][Add more sorters?]] +- [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] +- [[#default-sort][Default sort]] +- [[#dynamic-blocks][Dynamic blocks]] +- [[#fancier-plain-query-syntax-for-tags-and-properties][Fancier plain query syntax for tags and properties]] +- [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] +- [[#normalize-queries][Normalize queries]] +- [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] +- [[#recursive-queries][Recursive queries]] +- [[#timeline-view][Timeline view]] +- [[#update-view-screenshots][Update view screenshots]] +- [[#org-agenda-skip-function][org-agenda-skip-function]] +- [[#test-caching][Test caching]] +- [[#update-commentary][Update commentary]] +- [[#outline-path-predicate][Outline path predicate]] +- [[#node-caching]["Node" caching]] +- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] +- [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] +- [[#use-bovine-or-wisent-to-parse-non-sexp-syntax][Use Bovine or Wisent to parse non-sexp syntax]] +- [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#helm-command][Helm command]] +- [[#byte-compile-lambdas][Byte-compile lambdas]] +- [[#documentfigure-out-tag-inheritance][Document/figure out tag inheritance]] +- [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] +- [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] +- [[#use-macros-for-date][Use macros for date]] +:END: ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate @@ -53,160 +99,6 @@ This would be useful for having a menu of saved queries as Org links, or even bo *** DONE Save query from ql-agenda buffer -** UNDERWAY [#A] Outline path predicate - -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: - -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. - -** DONE [#A] Helm command - -In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. - -*** DONE Add - -*** DONE Demonstrate - -*** DONE Parsing non-Lisp queries - -[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror)) - ((predicate . args) (nreverse parsed))) - (when predicate - (list :predicate predicate :args args :combinator combinator))) - ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) -#+END_SRC - -I don't know where the =t= is coming from. - -The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (syntax-class whitespace)))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) -#+END_SRC - -In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. - -This seems to work, but we'll have to parse the args again in a separate step: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) -#+END_SRC - -Well, a bit of fiddling (lots of trial-and-error required) produced this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) -#+END_SRC - -That seems pretty usable! - ** TODO [#B] Add more sorters? + [ ] =category= @@ -220,6 +112,30 @@ For consistency, because plain ~auto~ looks like a variable, and even though it' Would probably be useful to have a default sort option. +** TODO Dynamic blocks + +For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. + +** TODO [#B] Fancier plain query syntax for tags and properties + +e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. + +[2020-02-13 Thu 00:42] Something is needed to help search property values by partial matches. For example: + +#+BEGIN_SRC org + ,* [[https://github.com/fniessen/org-html-themes][org-html-themes: Framework including two themes, Bigblow and ReadTheOrg]] + :PROPERTIES: + :author: Fabrice Niessen + :END: + +#+END_SRC + +Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. + +** TODO [#B] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] + +[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. + ** TODO [#B] Normalize queries [2019-07-16 Tue 11:49] This serves two purposes: @@ -310,6 +226,9 @@ This works pretty well. It needs polishing, and some refactoring so items can b #+END_SRC ** TODO [#B] Timeline view +:PROPERTIES: +:ID: 00573552-ffe9-4608-8904-7f6c73246b6d +:END: e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: @@ -372,6 +291,11 @@ e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-or 'face 'org-agenda-structure)) append (ht-get ts-ht ts)))) (org-ql-agenda--agenda nil nil :strings strings))) + + (org-ql-timeline* (org-agenda-files) + '(ts :from -14) + :filter-ts `(lambda (ts) + (ts<= ,(ts-adjust 'day -14 (ts-now)) ts))) #+END_SRC Another, more up-to-date implementation: @@ -450,88 +374,95 @@ Another, more up-to-date implementation: ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") #+END_SRC -** TODO [#B] Timeline view -:PROPERTIES: -:ID: 00573552-ffe9-4608-8904-7f6c73246b6d -:END: - -e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: - -#+BEGIN_SRC elisp - (cl-defun org-ql-timeline (buffers-files query) - (let ((results - (org-ql-select buffers-files - query :action - (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (timestamps - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (ts-parse-org (match-string 0)))) - (timestamp-strings - (->> timestamps - (-sort #'ts<) - (--map (concat " " (ts-format it)))))) - (s-join "\n" (cons heading-string timestamp-strings)))) - :sort '(date)))) - (org-ql-agenda--agenda nil nil :strings results))) - - (org-ql-timeline (org-agenda-files) - '(and "Emacs" (ts))) - - ;; More timeline-like version, organized by date rather than task. - - (cl-defun org-ql-timeline* (buffers-files query &key filter-ts) - (let* ((ts-ht (ht)) - (results (org-ql-select buffers-files - query - :action (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (date-timestamps - ;; Each one set to 00:00:00. - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (->> (match-string 0) - ts-parse-org - (ts-apply :hour 0 :minute 0 :second 0))))) - (setf date-timestamps (delete-dups date-timestamps)) - (when filter-ts - (setf date-timestamps (cl-remove-if-not filter-ts date-timestamps))) - (--each date-timestamps - (push heading-string (gethash it ts-ht))))))) - (tss-sorted (-sort #'ts< (ht-keys ts-ht))) - (strings (cl-loop for ts in tss-sorted - collect (concat "\n" - (propertize (ts-format "%Y-%m-%d" ts) - 'face 'org-agenda-structure)) - append (ht-get ts-ht ts)))) - (org-ql-agenda--agenda nil nil :strings strings))) - - (org-ql-timeline* (org-agenda-files) - '(ts :from -14) - :filter-ts `(lambda (ts) - (ts<= ,(ts-adjust 'day -14 (ts-now)) ts))) -#+END_SRC - [2019-09-26 Thu 21:28] Would probably make sense to implement this using the view-sections someday. ** TODO [#B] Update view screenshots e.g. doesn't currently show the =View= header. -** TODO Dynamic blocks +** TODO [#C] ~org-agenda-skip-function~ -For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. +As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: + +#+BEGIN_SRC elisp + ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- + + (defun org-ql-skip-function (query) + "Return a function for `org-agenda-skip-function' for QUERY. + Compared to using QUERY in `org-ql', this effectively turns QUERY + into (not QUERY)." + (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) + (lambda () + ;; This duplicates the functionality of `org-ql--select'. + (let (orig-fns) + (--each org-ql-predicates + ;; Save original function mappings. + (let ((name (plist-get it :name))) + (push (list :name name :fn (symbol-function name)) orig-fns))) + (unwind-protect + (progn + (--each org-ql-predicates + ;; Set predicate functions. + (fset (plist-get it :name) (plist-get it :fn))) + ;; Run query. + ;; FIXME: "If this function returns nil, the current match should not be skipped. + ;; Otherwise, the function must return a position from where the search + ;; should be continued." + (funcall predicate)) + (--each orig-fns + ;; Restore original function mappings. + (fset (plist-get it :name) (plist-get it :fn)))))))) + + (let ((org-agenda-custom-commands + '(("z" "Z" + ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) + ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) + ((org-agenda-files ("~/org/inbox.org")))))) + (org-agenda nil "z")) +#+END_SRC + +I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... + +** TODO [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + +** TODO [#C] Update commentary + +** UNDERWAY [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. ** UNDERWAY [#B] "Node" caching @@ -680,21 +611,6 @@ Appears to be another implementation of magit-section-like expandable sections. **** magit-section -** MAYBE Fancier plain query syntax for tags and properties - -e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. - -[2020-02-13 Thu 00:42] Something is needed to help search property values by partial matches. For example: - -#+BEGIN_SRC org - ,* [[https://github.com/fniessen/org-html-themes][org-html-themes: Framework including two themes, Bigblow and ReadTheOrg]] - :PROPERTIES: - :author: Fabrice Niessen - :END: -#+END_SRC - -Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. - ** MAYBE Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. @@ -703,6 +619,129 @@ Searching that with a query like =property:author=Fabrice= returns nothing; the They're both built-in to Emacs, so we could drop the =peg= dependency. +** MAYBE [#C] Fancier searching for inherited tags + +When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. + +** DONE [#A] Helm command + +In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. + +*** DONE Add + +*** DONE Demonstrate + +*** DONE Parsing non-Lisp queries + +[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror)) + ((predicate . args) (nreverse parsed))) + (when predicate + (list :predicate predicate :args args :combinator combinator))) + ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) +#+END_SRC + +I don't know where the =t= is coming from. + +The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (syntax-class whitespace)))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) + (quoted-arg "\"" unquoted-arg "\"") + (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) +#+END_SRC + +In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. + +This seems to work, but we'll have to parse the args again in a separate step: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) +#+END_SRC + +Well, a bit of fiddling (lots of trial-and-error required) produced this: + +#+BEGIN_SRC elisp + (-let* ((input "todo:check|someday") + (input "tags:universe+space") + (input "heading:\"spaced phrase\"") + (input "") + (input "heading:\"spaced phrase\"+another") + (input "heading:\"spaced phrase\"+another todo:check") + combinator + (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) + (and plain-string `(s -- (list :predicate 'regexp :args s)))) + (opt (+ (syntax-class whitespace) (any))))) + (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) + (predicate (substring keyword) ":" (opt args)) + (keyword (or "heading" "tags" "todo" "property")) + (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) + (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") + (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) + (separator (or (and "|" (action (setf combinator 'or))) + (and "+" (action (setf combinator 'and))) + (and ":" (action (setf combinator 'arg)))))) + input 'noerror))) + parsed) + ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) +#+END_SRC + +That seems pretty usable! + ** DONE Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] :LOGBOOK: @@ -941,112 +980,16 @@ If I made the =date= selector a macro, I could avoid the need to quote the compa Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc. -** TODO [#C] ~org-agenda-skip-function~ - -As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: - -#+BEGIN_SRC elisp - ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- - - (defun org-ql-skip-function (query) - "Return a function for `org-agenda-skip-function' for QUERY. - Compared to using QUERY in `org-ql', this effectively turns QUERY - into (not QUERY)." - (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) - (lambda () - ;; This duplicates the functionality of `org-ql--select'. - (let (orig-fns) - (--each org-ql-predicates - ;; Save original function mappings. - (let ((name (plist-get it :name))) - (push (list :name name :fn (symbol-function name)) orig-fns))) - (unwind-protect - (progn - (--each org-ql-predicates - ;; Set predicate functions. - (fset (plist-get it :name) (plist-get it :fn))) - ;; Run query. - ;; FIXME: "If this function returns nil, the current match should not be skipped. - ;; Otherwise, the function must return a position from where the search - ;; should be continued." - (funcall predicate)) - (--each orig-fns - ;; Restore original function mappings. - (fset (plist-get it :name) (plist-get it :fn)))))))) - - (let ((org-agenda-custom-commands - '(("z" "Z" - ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) - ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) - ((org-agenda-files ("~/org/inbox.org")))))) - (org-agenda nil "z")) -#+END_SRC - -I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... - -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** TODO [#C] Update commentary - -** MAYBE [#C] Fancier searching for inherited tags - -When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. - -* References - -** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] - -** [[gnus:gmane.emacs.orgmode#CAJ51EToLCm5zDLKu8XeuqEWrLhHZF+OoNkviPSivZbFttzF8=A@mail.gmail.com][John Kitchin on rewriting the Org agenda code]] :Emacs:Org: - -[2019-10-28 Mon 08:28] Originally from [[id:90a68535-2403-4ba9-a117-60be1862628f][this entry in my notes]]. - -#+BEGIN_QUOTE -From: John Kitchin -Subject: Re: [Orgmode] Slow speed of week and month views -Newsgroups: gmane.emacs.orgmode -To: Karl Voit -Cc: "emacs-orgmode@gnu.org" -Date: Sat, 5 Aug 2017 18:17:09 -0400 (4 hours, 11 minutes, 38 seconds ago) - -I can think of two possibilities for a future approach (besides a deep dive on profiling the current elisp to improve the speed there). They both involve some substantial coding though, and would probably add dependencies. I am curious what anyone things about these, or if there are other ideas. - -One is to use the new dynamic module capability to write an org parser in C, or a dedicated agenda function, which would presumably be faster than in elisp. This seems hard, and for me would certainly be a multiyear project I am sure! The downside of this is the need to compile the module. I don't know how easy it would be to make this work across platforms with the relatively easy install org-mode currently has. This could have a side benefit though of a c-lib that could be used by others to expand where org-mode is used. - -The other way that might work is to rely more heavily on a cached version of the files, perhaps in a different format than elisp, that is faster to work with. The approach I have explored in this is to index org files into a sqlite database. The idea then would be to generate the agenda from a sql query. I use something like this already to "find stuff in orgmode anywhere". One of the reasons I wrote this is the org-agenda list of files isn't practical for me because my files are so scattered on my file system. I had a need to be able to find TODOs in research projects in a pretty wide range of locations. - -The code I use is at https://github.com/jkitchin/scimax/blob/master/org-db.el, and from one database I can find headlines, contacts, locations, TODO headlines across my file system, all the files that contain a particular link, and my own recent org files. This approach relies on emacsql, and a set of hook functions to update the database whenever a file is changed. It is not robust, e.g. the file could be out of sync with the db if it is modified outside emacs, but this works well enough for me so far. Updated files get reindexed whenever emacs is idle. It was a compromise on walking the file system all the time or daily, or trying to use inotify and you can always run a command to prune/sync all the files any time you want. - -sqlite is ok, but with emacsql you cannot put strings in it directly (at least when I wrote the org-db code), which has limited it for full-text search so far. Also with text, the db got up to about 0.5 GB in size, and started slowing down. So it doesn't have text in it for now. It has all the other limitations of sqlite too, limited support for locking, single process.... - -I am moderately motivated to switch from sqlite to MongoDB, but the support for Mongo in emacs is pretty crummy (I tried writing a few traditional interfaces, but the performance was not that good, and limited since Mongo uses bson, and it is just not the same as json!). Why Mongo? Mostly because the Mongo query language is basically json and easy to generate in Emacs, unlike sql. Also, it is flexible and easy to adapt to new things, e.g. indexing src-blocks or tables or whatever org-element you want. (And I want to use Mongo for something else too ;). Obviously these all add dependencies, and might not be suitable for the core org-mode distribution. But I do think it is important to think about ways to scale org-mode while maintaining compatibility with the core. - -The main point of the database was to get a query language, persistence and good performance. I have also used caches to speed up using bibtex files, and my org-contacts with reasonable performance. These have been all elisp, with no additional dependencies. Maybe one could do something similar to keep an agenda cache that is persistent and updated via hook functions. - -Thoughts? - -John -#+END_QUOTE -:PROPERTIES: -:archive.is: http://archive.is/33R9M -:END: - -+ [[https://github.com/m00natic/cl-fdbq][GitHub - m00natic/cl-fdbq: SQL-like operations over fixed field DBs]] - -** Nicolas Goaziou's =org-element= cache implementation - -[2020-01-04 Sat 08:31] https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el#L4817 I guess I haven't been keeping up, because I'm not sure when exactly he made or committed this, or what his plans for it are. It's currently disabled by default. - -** [[https://github.com/ndwarshuis/org-sql][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] - -[2020-01-04 Sat 09:03] - * Examples / testing +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: +:CONTENTS: +- [[#property-matching][Property matching]] +- [[#regexp-matching][Regexp matching]] +- [[#screenshot-code][Screenshot code]] +- [[#sorting][Sorting]] +:END: #+BEGIN_SRC elisp (org-agenda-ng org-agenda-files @@ -1083,6 +1026,37 @@ John (done))) #+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 + +** Regexp matching + +#+BEGIN_SRC elisp + (org-ql "~/src/emacs/org-super-agenda/test/test.org" + (regexp "over")) + + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (regexp "over")) +#+END_SRC + +** Screenshot code + +#+BEGIN_SRC elisp + (org-super-agenda--test-with-org-today-date "2017-07-08 00:00" + (org-ql "~/src/emacs/org-super-agenda/test/test.org" + (and (or (date = today) + (deadline <=) + (scheduled <= today)) + (not (done))))) +#+END_SRC + ** Sorting #+BEGIN_SRC elisp @@ -1099,38 +1073,14 @@ John :sort (todo)) #+END_SRC -** Regexp matching - -#+BEGIN_SRC elisp - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (regexp "over")) - - (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (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 - (org-super-agenda--test-with-org-today-date "2017-07-08 00:00" - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date = today) - (deadline <=) - (scheduled <= today)) - (not (done))))) -#+END_SRC - * In the wild +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: +:CONTENTS: +- [[#alois-janicek][Alois Janicek]] +- [[#benson-chu][Benson Chu]] +:END: ** [[https://github.com/AloisJanicek/.doom.d-2nd][Alois Janicek]] @@ -1226,6 +1176,427 @@ John #+END_SRC * Profiling +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: + +:CONTENTS: +- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][{2019-08-29 Thu 06:24} Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] +- [[#caching-of-inherited-tags][Caching of inherited tags]] +- [[#intersecting-query-results][Intersecting query results]] +- [[#more-profiling][More profiling]] +- [[#preambles][Preambles]] +- [[#profiling-flet-across-all-agenda-files][Profiling flet across all agenda files]] +- [[#profiling-flet-on-a-single-file][Profiling flet on a single file]] +- [[#profiling-org-trust-scanner-tags][Profiling org-trust-scanner-tags]] +- [[#profiling-position-based][Profiling position-based]] +- [[#profiling-tags-matching][Profiling tags matching]] +- [[#using-org-element-parse-buffer][Using org-element-parse-buffer]] +- [[#withwithout-tsel][with/without ts.el]] +:END: + + +** [2019-08-29 Thu 06:24] Benchmarking org-ql compared to re-search-forward for getting headings in buffer +:PROPERTIES: +:ID: fcc09229-ed24-42eb-a1fd-31d8f7d4c8d5 +:END: + +Minimal difference, and that's a very large file, too. On smaller files it's thousandths of a second. + +#+BEGIN_SRC elisp + (with-current-buffer (find-buffer-visiting "~/org/inbox.org") + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("org-ql" (org-ql-select (current-buffer) + '(level 1) + :action '(progn + (font-lock-ensure (line-beginning-position) (line-end-position)) + (cons (org-get-heading t) (point))))) + ("re-search-forward" (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop while (re-search-forward (rx bol "*" (1+ blank)) nil t) + do (font-lock-ensure (line-beginning-position) (line-end-position)) + collect (cons (org-get-heading t) (match-beginning 0)))))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|-------------------+--------------------+---------------+----------+------------------| +| re-search-forward | 1.17 | 0.520375 | 0 | 0 | +| org-ql | slowest | 0.608281 | 0 | 0 | + +** Caching of inherited tags + +[2019-09-05 Thu 07:59] Implemented a per-buffer tags cache that seems to significantly speed up tags queries that use tag inheritance. It persists as long as the buffer remains unmodified, and it's usable from any code as a single function that automatically uses caching. It also returns inherited tags and local tags separately, which could be useful for having separate selectors, one for inherited tags, one for local tags, and one for both. + +#+BEGIN_SRC elisp + (defvar org-ql-tags-cache (ht) + "Per-buffer tags cache. + Keyed by buffer. Each value is a cons of the buffer's modified + tick, and another hash table keyed on buffer position, whose + values are a list of two lists, inherited tags and local tags, as + strings.") + + (defun org-ql--tags-at (position) + "Return tags for POSITION in current buffer. + Returns cons (INHERITED-TAGS . LOCAL-TAGS)." + ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables + ;; bound in the else clause, so destructured variables that are non-nil, + ;; like found caches, are not available in the else clause. + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) + (modified-tick (car buffer-cache)) + (tags-cache (cdr buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cached-result (gethash position tags-cache))) + ;; Found in cache: return them. + (pcase cached-result + ('org-ql-nil nil) + (_ cached-result)) + ;; Not found in cache: get tags and cache them. + (let* ((local-tags (or (org-get-tags position 'local) + 'org-ql-nil)) + (inherited-tags (or (save-excursion + (when (org-up-heading-safe) + (-let* (((inherited local) (org-ql--tags-at (point))) + (inherited-tags (when (or inherited local) + (cond ((and (listp inherited) + (listp local)) + (append inherited local)) + ((cond ((listp inherited) inherited) + ((listp local) local))))))) + (when inherited-tags + (->> inherited-tags -non-nil -uniq))))) + 'org-ql-nil)) + (all-tags (list inherited-tags local-tags))) + ;; Check caches again, because they may have been set now. + ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? + (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) + modified-tick (car buffer-cache) + tags-cache (cdr buffer-cache) + buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cond ((or (not buffer-cache) + (not buffer-unmodified-p)) + ;; Buffer-local tags cache empty or invalid: make new one. + (puthash (current-buffer) + (cons (buffer-modified-tick) + (let ((table (make-hash-table))) + (puthash position all-tags table) + table)) + org-ql-tags-cache) + ;; Return tags, not the cons put on the buffer-cache. + all-tags) + ;; Buffer-local tags cache found, but no result: store this one. + (t (puthash position all-tags tags-cache)))))) + + (org-ql--defpred tags-cached (&rest tags) + "Return non-nil if current heading has one or more of TAGS (a list of strings)." + ;; TODO: Try to use `org-make-tags-matcher' to improve performance. It would be nice to not have + ;; to run `org-get-tags' for every heading, especially with inheritance. + (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((inherited local) (org-ql--tags-at (point)))) + (cl-typecase tags + (null (or (tags-p inherited) + (tags-p local))) + (otherwise (or (when (tags-p inherited) + (seq-intersection tags inherited)) + (when (tags-p local) + (seq-intersection tags local)))))))) +#+END_SRC + +Benchmark results: + +#+BEGIN_SRC elisp + (let* ((buffers '("~/org/main.org")) + (tags '("Emacs"))) + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("uncached" (let ((org-ql-cache (ht))) + (org-ql-select buffers + `(tags ,@tags)))) + ("cached" (let ((org-ql-cache (ht)) + (org-ql-tags-cache (ht))) + (org-ql-select buffers + `(tags-cached ,@tags))))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------+--------------------+---------------+----------+------------------| +| cached | 6.51 | 0.519871 | 0 | 0 | +| uncached | slowest | 3.386679 | 0 | 0 | + +** Intersecting query results + +An idea that /might/ be helpful for performance in /some/ cases, depending on the query, the data, and whether the query has a preamble. But it looks like it would very rarely be helpful. + +#+BEGIN_SRC elisp + (cl-defun org-ql-agenda-intersection (buffers-files queries &key entries sort buffer narrow super-groups) + "Like `org-ql-agenda', but intersects multiple queries." + (declare (indent defun)) + (let* ((org-ql-cache (ht)) + (entries (->> queries + (--map (org-ql-select buffers-files + it + :action 'element-with-markers + :narrow narrow + :sort sort)) + (-reduce #'-intersection)))) + (org-ql-agenda--agenda buffers-files queries + :entries entries :super-groups super-groups))) + + (bench-multi-lexical :times 1 + :forms (("intersection" (let ((org-use-tag-inheritance nil)) + (org-ql-agenda-intersection (org-agenda-files) + '((todo "TODO") + (tags "Emacs")) + :sort '(priority deadline) + :super-groups org-super-agenda-groups))) + ("normal" (let ((org-use-tag-inheritance nil)) + (org-ql-agenda (org-agenda-files) + (and (todo "TODO") + (tags "Emacs")) + :sort (priority deadline) + :super-groups org-super-agenda-groups))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|--------------+--------------------+---------------+----------+------------------| +| normal | 3.70 | 0.233147 | 0 | 0 | +| intersection | slowest | 0.862512 | 0 | 0 | + +*** Alternative approach + +[2019-09-01 Sun 08:17] This is very experimental, but the results are surprising. When the action function returns a fairly simple list, the intersection is very slightly faster. When returning full elements, the intersection is much slower, so that it more than doubles the runtime. I wonder if the element list comparison is short-circuiting, or if it looks at the whole lists, because it seems like it shouldn't take more than 4-5 list elements before it realizes that two lists don't match. + +Anyway, looks like this approach isn't viable, at least not without a much more complicated implementation, which probably wouldn't be worth it. + +#+BEGIN_SRC elisp + (let* ((action-fn (lambda () + (list (current-buffer) + (point) + (substring-no-properties (org-get-heading t t))))) + (files '("~/org/main.org"))) + ;; NOTE: Careful to use the same files and action in each one. I duplicated + ;; the variable in each form to make individual testing easier. + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("normal" (->> (let ((org-ql-cache (ht)) + (action-fn (lambda () + (list (current-buffer) + (point) + (substring-no-properties (org-get-heading t t))))) + (files '("~/org/main.org"))) + (org-ql-select files + '(and (not (done)) + (or (habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + :action action-fn)))) + ("Testing" (let* ((org-ql-cache (ht)) + (files '("~/org/main.org")) + (action-fn (lambda () + (list (current-buffer) + (point) + (substring-no-properties (org-get-heading t t))))) + (and-queries '(not (done))) + (or-queries '((habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + (and-results (org-ql-select files + and-queries + :action action-fn)) + (or-results (cl-loop for query in or-queries + append (org-ql-select files + query + :action action-fn)))) + (seq-intersection and-results + (->> or-results + -uniq))))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|---------+--------------------+---------------+----------+------------------| +| Testing | 1.15 | 0.248376 | 0 | 0 | +| normal | slowest | 0.284897 | 0 | 0 | + +#+BEGIN_SRC elisp + +;; With caching enabled + (let* ((action-fn (lambda () + (list (current-buffer) + (point) + (substring-no-properties (org-get-heading t t))))) + (files '("~/org/main.org"))) + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("normal" (->> (org-ql-select files + '(and (not (done)) + (or (habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + :action action-fn))) + ("Testing" (let* ((files '("~/org/main.org")) + (and-queries '(not (done))) + (or-queries '((habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + (and-results (org-ql-select files + and-queries + :action action-fn)) + (or-results (cl-loop for query in or-queries + append (org-ql-select files + query + :action action-fn)))) + (seq-intersection and-results + (->> or-results + -uniq))))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|---------+--------------------+---------------+----------+------------------| +| normal | 13.72 | 0.002311 | 0 | 0 | +| Testing | slowest | 0.031707 | 0 | 0 | + +Using full views: + +#+BEGIN_SRC elisp + (let* ((action-fn (lambda () + (list (current-buffer) + (point) + (substring-no-properties (org-get-heading t t))))) + (files '("~/org/main.org"))) + (bench-multi-lexical :times 1 + :forms (("normal" (->> (let ((org-ql-cache (ht)) + (files '("~/org/main.org"))) + (org-ql-search files + '(and (not (done)) + (or (habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))))))) + ("Testing" (let* ((org-ql-cache (ht)) + (files '("~/org/main.org")) + (and-queries '(not (done))) + (or-queries '((habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + (and-results (org-ql-select files + and-queries + :action 'element-with-markers)) + (or-results (cl-loop for query in or-queries + append (org-ql-select files + query + :action 'element-with-markers))) + (final-results (seq-intersection and-results + (->> or-results + -uniq)))) + (org-ql-agenda--agenda nil nil + :entries final-results) + + ))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|---------+--------------------+---------------+----------+------------------| +| normal | 1.74 | 0.534742 | 0 | 0 | +| Testing | slowest | 0.931897 | 0 | 0 | + +Just gathering results, but using elements: + +#+BEGIN_SRC elisp + (let* ((action-fn 'element-with-markers) + (files '("~/org/main.org"))) + ;; NOTE: Careful to use the same files and action in each one. I duplicated + ;; the variable in each form to make individual testing easier. + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("normal" (->> (let ((org-ql-cache (ht))) + (org-ql-select files + '(and (not (done)) + (or (habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + :action action-fn)))) + ("Testing" (let* ((org-ql-cache (ht)) + (and-queries '(not (done))) + (or-queries '((habit) + (deadline auto) + (scheduled :to today) + (ts-active :on today) + (closed :on today))) + (and-results (org-ql-select files + and-queries + :action action-fn)) + (or-results (cl-loop for query in or-queries + append (org-ql-select files + query + :action action-fn)))) + (seq-intersection and-results + (->> or-results + -uniq))))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|---------+--------------------+---------------+----------+------------------| +| normal | 2.27 | 0.314218 | 0 | 0 | +| Testing | slowest | 0.714587 | 0 | 0 | + + +** More profiling + +[2018-05-10 Thu 15:02] I think these are decent improvements. + +#+BEGIN_SRC elisp + (elp-profile 1 nil (org-agenda-ng "~/org/main.org" + (or (habit) + (and (or (date '= (org-today)) + (deadline '<=) + (scheduled '<= (org-today))) + (not (apply #'todo org-done-keywords-for-agenda))) + (and (todo "DONE" "CANCELLED") + (closed '= (org-today)))))) +#+END_SRC + +#+RESULTS: +| Function | Times called | Total time | Average time | +|-------------------------------+--------------+--------------+--------------| +| mapcar | 164 | 1.5004585290 | 0.0091491373 | +| org-agenda-ng--agenda | 1 | 1.348231247 | 1.348231247 | +| org-agenda-ng--filter-buffer | 1 | 1.1391189879 | 1.1391189879 | +| org-agenda-ng--date-plain-p | 1267 | 0.6198571040 | 0.0004892321 | +| org-entry-get | 3983 | 0.2979337370 | 7.480...e-05 | +| org-is-habit-p | 1365 | 0.2049101109 | 0.0001501172 | +| org--property-local-values | 1365 | 0.1940614150 | 0.0001421695 | +| org-agenda-ng--habit-p | 1272 | 0.1911009179 | 0.0001502365 | +| org-agenda-ng--format-element | 52 | 0.177965411 | 0.0034224117 | +| org-get-property-block | 1365 | 0.1760004519 | 0.0001289380 | +| org-get-tags-at | 52 | 0.1362824969 | 0.0026208172 | +| org-agenda-ng--date-p | 3880 | 0.1351176629 | 3.482...e-05 | +| org-up-heading-safe | 226 | 0.1276747609 | 0.0005649325 | +| re-search-backward | 2028 | 0.1144211070 | 5.642...e-05 | +| org-entry-properties | 2618 | 0.0848660999 | 3.241...e-05 | +| org-agenda-ng--todo-p | 1319 | 0.081952653 | 6.213...e-05 | +| org-get-todo-state | 1319 | 0.0796836810 | 6.041...e-05 | +| re-search-forward | 3754 | 0.0739803739 | 1.970...e-05 | +| org-inlinetask-in-task-p | 1365 | 0.0657829330 | 4.819...e-05 | +| org-agenda-ng--scheduled-p | 1247 | 0.0619497850 | 4.967...e-05 | ** Preambles @@ -1568,127 +1939,448 @@ Not sure why that one is slower with preamble. | no preamble: (ts-i :to "2019-07-06") | 1.34 | 0.553428 | 0 | 0 | | preamble: (ts-i :to "2019-07-06") | slowest | 0.743881 | 0 | 0 | -** with/without ts.el +** Profiling flet across all agenda files -[2019-08-11 Sun 15:39] These results seem to show a minor performance improvement by using ~ts~, and the code is simpler. +*** With flet #+BEGIN_SRC elisp - ;; (require 'ts) - - (org-ql--defpred ts-ts (&key from to _on) - ;; The underscore before `on' prevents "unused lexical variable" warnings, because we - ;; pre-process that argument in a macro before this function is called. - "Return non-nil if current entry has a timestamp in given period. - If no arguments are specified, return non-nil if entry has any - timestamp. - - If FROM, return non-nil if entry has a timestamp on or after - FROM. - - If TO, return non-nil if entry has a timestamp on or before TO. - - If ON, return non-nil if entry has a timestamp on date ON. - - FROM, TO, and ON should be strings parseable by - `parse-time-string' but may omit the time value." - ;; TODO: DRY this with the clocked predicate. - ;; NOTE: FROM and TO are actually expected to be Unix timestamps. The docstring is written - ;; for end users, for which the arguments are pre-processed by `org-ql-select'. - ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. - (cl-macrolet ((next-timestamp () - `(when (re-search-forward org-element--timestamp-regexp end-pos t) - (ts-parse-org (match-string 0)))) - (test-timestamps (pred-form) - `(cl-loop for next-ts = (next-timestamp) - while next-ts - thereis ,pred-form))) - (save-excursion - (let ((end-pos (org-entry-end-position))) - (cond ((not (or from to)) (re-search-forward org-element--timestamp-regexp end-pos t)) - ((and from to) (test-timestamps (and (ts<= from next-ts) - (ts<= next-ts to)))) - (from (test-timestamps (ts<= from next-ts))) - (to (test-timestamps (ts<= next-ts to)))))))) - -#+END_SRC - -*** Without timestamp argument - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts))))) + (elp-profile 5 (org-agenda-ng--agenda + :files org-agenda-files + :pred (lambda () + (and (todo) + (or (date :deadline '<= (org-today)) + (date :scheduled '<= (org-today))) + (not (apply #'todo org-done-keywords-for-agenda)))))) #+END_SRC #+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.14 | 2.251801 | 0 | 0 | -| old ts | slowest | 2.560280 | 0 | 0 | +#+begin_example +mapcar 711 25.608392569 0.0360174297 +org-agenda-ng--agenda 5 24.019318793 4.8038637586 +org-agenda-ng--filter-buffer 40 14.160293256 0.3540073313 +org-agenda-ng--date-p 21595 4.2111783960 0.0001950071 +org-agenda-finalize-entries 5 4.0930243110 0.8186048622 +org-super-agenda--filter-finalize-entries 5 3.937522006 0.7875044012 +org-agenda-ng--todo-p 37080 3.5687476730 9.624...e-05 +org-get-todo-state 37080 3.4737076600 9.368...e-05 +outline-next-heading 34625 3.4689080650 0.0001001850 +re-search-forward 42280 3.0743315830 7.271...e-05 +org-agenda-ng--format-element 1180 2.9511605820 0.0025009835 +org-element-headline-parser 1180 2.6757063699 0.0022675477 +org-super-agenda--group-items 5 2.187362092 0.4374724183 +org-super-agenda--group-dispatch 70 2.184685662 0.0312097951 +org-entry-get 22730 2.0711872869 9.112...e-05 +org-entry-properties 21595 1.8958912070 8.779...e-05 +org-super-agenda--group-tag 25 1.8498977799 0.0739959111 +org-element-timestamp-parser 3785 1.8234333229 0.0004817525 +org-parse-time-string 7560 1.7121709579 0.0002264776 +org-element--get-time-properties 1180 1.1814058020 0.0010011913 +#+end_example + +*** Without flet #+BEGIN_SRC elisp - (bench-multi-lexical :times 20 :ensure-equal t - :forms (("old ts" (org-ql "~/src/emacs/org-ql/tests/data.org" - (ts))) - ("ts.el ts" (org-ql "~/src/emacs/org-ql/tests/data.org" - (ts-ts))))) + (elp-profile 5 (org-agenda-ng--agenda + :files org-agenda-files + :pred (lambda () + (and (org-agenda-ng--todo-p) + (or (org-agenda-ng--date-p :deadline '<= (org-today)) + (org-agenda-ng--date-p :scheduled '<= (org-today))) + (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) #+END_SRC #+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.05 | 0.103714 | 0 | 0 | -| old ts | slowest | 0.108663 | 0 | 0 | +#+begin_example +mapcar 711 26.910164986 0.0378483333 +org-agenda-ng--agenda 5 21.012501837 4.2025003674 +org-agenda-ng--filter-buffer 40 13.751964650 0.3437991162 +org-agenda-ng--todo-p 37080 5.8788306440 0.0001585445 +org-agenda-ng--format-element 1180 4.5712275970 0.0038739216 +org-get-todo-state 37080 4.1661659069 0.0001123561 +org-agenda-ng--date-p 21595 4.1442710769 0.0001919088 +org-entry-get 22730 2.8275069239 0.0001243953 +org-entry-properties 21595 2.6558403739 0.0001229840 +outline-next-heading 34625 2.0894695999 6.034...e-05 +org-element-headline-parser 1180 1.9110445780 0.0016195293 +re-search-forward 42280 1.6994989150 4.019...e-05 +org-agenda-ng--add-faces 1180 1.6172592580 0.0013705586 +org-agenda-ng--add-scheduled-face 1180 1.607386145 0.0013621916 +org-get-tags-at 1180 1.1521010509 0.0009763568 +org-back-to-heading 64530 1.1005834200 1.705...e-05 +org-up-heading-safe 2360 1.0182265390 0.0004314519 +outline-back-to-heading 64530 1.0086056729 1.563...e-05 +org-parse-time-string 7560 0.8314918499 0.0001099856 +org-time-string-to-absolute 3780 0.8277485280 0.0002189810 +#+end_example -*** :from + +** Profiling flet on a single file + +This shows that the difference between them, if any, is so small as to be irrelevant. The convenience and clarity are a big win. + +*** With flet #+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :from "2017-01-01"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :from "2017-01-01"))))) + (elp-profile 5 (org-agenda-ng--agenda + :files "~/org/main.org" + :pred (lambda () + (and (todo) + (or (date :deadline '<= (org-today)) + (date :scheduled '<= (org-today))) + (not (apply #'todo org-done-keywords-for-agenda)))))) #+END_SRC #+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.32 | 1.299966 | 0 | 0 | -| old ts | slowest | 1.713027 | 0 | 0 | +#+begin_example +mapcar 526 3.7898506779 0.0072050393 +org-agenda-ng--agenda 5 2.7695176850 0.5539035370 +org-agenda-ng--filter-buffer 5 1.414347774 0.2828695548 +org-agenda-ng--format-element 265 0.8871611419 0.0033477778 +org-get-tags-at 265 0.7891641319 0.0029779778 +org-up-heading-safe 1150 0.7581951110 0.0006593000 +re-search-backward 3700 0.5948686769 0.0001607753 +org-agenda-ng--todo-p 6690 0.5840980579 8.730...e-05 +org-get-todo-state 6690 0.5666448919 8.470...e-05 +org-agenda-ng--date-p 5940 0.5196037069 8.747...e-05 +org-entry-get 6195 0.4144106150 6.689...e-05 +org-entry-properties 5940 0.3640680380 6.129...e-05 +org-element-headline-parser 265 0.2810144920 0.0010604320 +outline-next-heading 6195 0.2495287770 4.027...e-05 +org-back-to-heading 14565 0.1959557380 1.345...e-05 +re-search-forward 7850 0.1933439489 2.462...e-05 +outline-back-to-heading 14565 0.1753121230 1.203...e-05 +org-outline-level 2300 0.1676228200 7.287...e-05 +org-agenda-finalize-entries 5 0.1607656930 0.0321531386 +org-super-agenda--filter-finalize-entries 5 0.1316961509 0.0263392301 +#+end_example -*** :to +*** Without flet #+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :to "2019-01-01"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :to "2019-01-01"))))) + (elp-profile 5 (org-agenda-ng--agenda + :files "~/org/main.org" + :pred (lambda () + (and (org-agenda-ng--todo-p) + (or (org-agenda-ng--date-p :deadline '<= (org-today)) + (org-agenda-ng--date-p :scheduled '<= (org-today))) + (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) #+END_SRC #+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.01 | 1.300084 | 0 | 0 | -| old ts | slowest | 1.312208 | 0 | 0 | +#+begin_example +mapcar 526 3.7766218089 0.0071798893 +org-agenda-ng--agenda 5 2.75718831 0.551437662 +org-agenda-ng--filter-buffer 5 1.402551392 0.2805102784 +org-agenda-ng--format-element 265 0.8864161399 0.0033449665 +org-get-tags-at 265 0.7896260759 0.0029797210 +org-up-heading-safe 1150 0.7589292910 0.0006599385 +re-search-backward 3700 0.5956338739 0.0001609821 +org-agenda-ng--todo-p 6690 0.5781650060 8.642...e-05 +org-get-todo-state 6690 0.5603983020 8.376...e-05 +org-agenda-ng--date-p 5940 0.5209897369 8.770...e-05 +org-entry-get 6195 0.4158440950 6.712...e-05 +org-entry-properties 5940 0.3640524090 6.128...e-05 +org-element-headline-parser 265 0.2810144710 0.0010604319 +outline-next-heading 6195 0.2485497380 4.012...e-05 +org-back-to-heading 14565 0.1957209180 1.343...e-05 +re-search-forward 7850 0.1927130979 2.454...e-05 +outline-back-to-heading 14565 0.1751091780 1.202...e-05 +org-outline-level 2300 0.1680958539 7.308...e-05 +org-agenda-finalize-entries 5 0.1610422239 0.0322084448 +org-super-agenda--filter-finalize-entries 5 0.132423043 0.0264846085 +#+end_example -*** :on + +** Profiling =org-trust-scanner-tags= + +[2018-05-10 Thu 12:59] Turned on =org-trust-scanner-tags=, going to try profiling again: #+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :on "2019-05-14"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :on "2019-05-14"))))) + ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + ;; (tags "world"))) + + (elp-profile 10 nil (org-agenda-ng org-agenda-files + (tags "Emacs"))) #+END_SRC #+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.17 | 0.557281 | 0 | 0 | -| old ts | slowest | 0.652149 | 0 | 0 | +| Function | Times called | Total time | Average time | +|-------------------------------------------+--------------+--------------+--------------| +| org-agenda-ng--agenda | 10 | 44.092598282 | 4.4092598282 | +| mapcar | 282 | 40.234516707 | 0.1426755911 | +| org-agenda-ng--filter-buffer | 80 | 26.895492471 | 0.3361936558 | +| org-element-headline-parser | 3980 | 10.387614362 | 0.0026099533 | +| org-agenda-finalize-entries | 10 | 9.194458252 | 0.9194458252 | +| org-agenda-ng--tags-p | 70250 | 8.1897379849 | 0.0001165799 | +| org-agenda-ng--format-element | 3980 | 6.5944325679 | 0.0016568926 | +| outline-next-heading | 70320 | 6.1190180490 | 8.701...e-05 | +| re-search-forward | 97050 | 5.8706467829 | 6.049...e-05 | +| org-get-tags-at | 74230 | 5.4078158059 | 7.285...e-05 | +| org-super-agenda--filter-finalize-entries | 10 | 5.2320123400 | 0.5232012340 | +| org-super-agenda--group-items | 10 | 5.1260959210 | 0.5126095921 | +| org-super-agenda--group-dispatch | 130 | 5.119333624 | 0.0393794894 | +| sort | 20 | 3.8204368569 | 0.1910218428 | +| org-element--parse-objects | 6180 | 3.5386578929 | 0.0005725983 | +| org-is-habit-p | 5970 | 3.2497755920 | 0.0005443510 | +| org-entry-get | 5970 | 3.2347964049 | 0.0005418419 | +| org--property-local-values | 5970 | 3.1796357319 | 0.0005326023 | +| org-get-property-block | 5970 | 3.0767919680 | 0.0005153755 | +| org-entries-lessp | 20020 | 2.6563960079 | 0.0001326871 | + +Now trying again without it: + +#+BEGIN_SRC elisp + ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + ;; (tags "world"))) + + (elp-profile 10 nil (org-agenda-ng org-agenda-files + (tags "Emacs"))) +#+END_SRC + +#+RESULTS: +| Function | Times called | Total time | Average time | +|-------------------------------------------+--------------+--------------+--------------| +| mapcar | 1791 | 57.096304538 | 0.0318795670 | +| org-agenda-ng--agenda | 10 | 54.232133506 | 5.4232133505 | +| org-agenda-ng--filter-buffer | 80 | 30.065167040 | 0.3758145880 | +| org-get-tags-at | 74230 | 13.840202495 | 0.0001864502 | +| org-agenda-ng--format-element | 3980 | 13.429297797 | 0.0033741954 | +| org-element-headline-parser | 3980 | 12.771776652 | 0.0032089891 | +| org-agenda-finalize-entries | 10 | 9.1439433990 | 0.9143943399 | +| org-agenda-ng--tags-p | 70250 | 9.0249653730 | 0.0001284692 | +| org-super-agenda--filter-finalize-entries | 10 | 7.300515859 | 0.7300515859 | +| outline-next-heading | 70320 | 7.2384435649 | 0.0001029357 | +| org-super-agenda--group-items | 10 | 4.918585855 | 0.4918585855 | +| org-super-agenda--group-dispatch | 130 | 4.9125893509 | 0.0377891488 | +| re-search-forward | 101020 | 4.6294823850 | 4.582...e-05 | +| org-up-heading-safe | 7370 | 4.4629885620 | 0.0006055615 | +| org-is-habit-p | 5960 | 4.2772351910 | 0.0007176569 | +| org-entry-get | 5960 | 4.2595350800 | 0.0007146870 | +| org-super-agenda--group-tag | 50 | 3.8942044929 | 0.0778840898 | +| re-search-backward | 26150 | 3.3660083490 | 0.0001287192 | +| org--property-local-values | 5960 | 3.1793476329 | 0.0005334475 | +| org-get-property-block | 5960 | 3.0662425979 | 0.0005144702 | + +Wow, using =org-trust-scanner-tags= saves a /lot/ of time. + +** Profiling position-based + +*** Macro + +#+BEGIN_SRC elisp + (defmacro elp-profile (times &rest body) + (declare (indent defun)) + `(let ((prefixes '("org-" "string-" "s-" "buffer-" "append" "delq" "map" + "list" "car" "save-" "outline-" "delete-dups" + "sort" "line-" "nth" "concat" "char-to-string" + "rx-" "goto-" "when" "search-" "re-")) + output) + (dolist (prefix prefixes) + (elp-instrument-package prefix)) + (dotimes (x ,times) + ,@body) + (elp-results) + (elp-restore-all) + (point-min) + (forward-line 20) + (delete-region (point) (point-max)) + (setq output (buffer-substring-no-properties (point-min) (point-max))) + (kill-buffer) + (delete-window) + output)) +#+END_SRC + + +*** ng-flet + +#+BEGIN_SRC elisp + (elp-profile 5 (org-agenda-ng--test-agenda-today)) +#+END_SRC + +#+RESULTS: +#+begin_example +mapcar 121 0.1292609089 0.0010682719 +org-agenda-ng--test-agenda-today 5 0.0860146149 0.017202923 +org-agenda-ng--agenda 5 0.0858901769 0.0171780353 +org-agenda-ng--format-element 75 0.0308815090 0.0004117534 +org-agenda-ng--filter-buffer 5 0.026709027 0.0053418054 +org-agenda-ng--date-p 455 0.0210552310 4.627...e-05 +org-element-headline-parser 75 0.016209908 0.0002161321 +org-get-tags-at 75 0.008953666 0.0001193822 +org-agenda-ng--add-faces 75 0.0072834109 9.711...e-05 +org-element-timestamp-interpreter 150 0.0068781430 4.585...e-05 +org-entry-get 290 0.0060815609 2.097...e-05 +org-up-heading-safe 210 0.005708647 2.718...e-05 +org-agenda-finalize-entries 5 0.005201221 0.0010402442 +org-element-timestamp-parser 150 0.005191617 3.461078e-05 +org-entry-properties 290 0.0048787450 1.682...e-05 +org-element--get-time-properties 75 0.004112675 5.483...e-05 +org-agenda-ng--add-deadline-face 75 0.0039314910 5.241...e-05 +org-back-to-heading 725 0.0037559990 5.180...e-06 +org-agenda-ng--add-scheduled-face 75 0.0031766149 4.235...e-05 +org-parse-time-string 300 0.0031740200 1.058...e-05 +#+end_example + +*** ng-funcall + +#+BEGIN_SRC elisp + (elp-profile 5 (org-agenda-ng--test-agenda-today)) +#+END_SRC + +#+RESULTS: +#+begin_example +mapcar 121 0.1296645480 0.0010716078 +org-agenda-ng--test-agenda-today 5 0.086714029 0.0173428058 +org-agenda-ng--agenda 5 0.086584611 0.0173169222 +org-agenda-ng--format-element 75 0.0307461019 0.0004099480 +org-agenda-ng--filter-buffer 5 0.027136826 0.0054273652 +org-agenda-ng--date-p 455 0.0213037090 4.682...e-05 +org-element-headline-parser 75 0.016251755 0.0002166900 +org-get-tags-at 75 0.008959605 0.0001194614 +org-agenda-ng--add-faces 75 0.0072381410 9.650...e-05 +org-element-timestamp-interpreter 150 0.0069832960 4.655...e-05 +org-entry-get 290 0.0061220340 2.111...e-05 +org-up-heading-safe 210 0.0057036860 2.716...e-05 +org-agenda-finalize-entries 5 0.005372899 0.0010745798 +org-element-timestamp-parser 150 0.0050518689 3.367...e-05 +org-entry-properties 290 0.0049517209 1.707...e-05 +org-agenda-ng--add-deadline-face 75 0.0039273909 5.236...e-05 +org-element--get-time-properties 75 0.0039059429 5.207...e-05 +org-back-to-heading 725 0.0037793259 5.212...e-06 +org-parse-time-string 300 0.0032196259 1.073...e-05 +org-agenda-ng--add-scheduled-face 75 0.0031410580 4.188...e-05 +#+end_example + +*** orig + +Make sure to kill any existing agenda buffers first. + +#+BEGIN_SRC elisp + (elp-profile 1 (org-agenda-list nil nil 'week)) +#+END_SRC + +#+RESULTS: +#+begin_example +org-agenda-list 1 9.693596196 9.693596196 +org-agenda-get-day-entries 56 8.630330659 0.1541130474 +org-agenda-get-scheduled 56 6.6207980570 0.1182285367 +org-is-habit-p 2792 2.2907458449 0.0008204677 +org-entry-get 2798 2.287390186 0.0008175090 +org-agenda--timestamp-to-absolute 7708 2.0970420100 0.0002720604 +org-agenda-get-deadlines 56 1.6941886389 0.0302533685 +org-at-planning-p 4399 1.3993312159 0.0003181021 +org--property-local-values 2793 1.2699226760 0.0004546805 +org-get-property-block 2794 1.2182695930 0.0004360306 +org-time-string-to-absolute 7708 1.1513844880 0.0001493752 +org-inlinetask-in-task-p 6969 1.139932302 0.0001635718 +org-parse-time-string 7880 1.0635759220 0.0001349715 +org-closest-date 3864 1.0383435800 0.0002687224 +re-search-forward 15199 0.9607921779 6.321...e-05 +org-back-to-heading 12667 0.8564486210 6.761...e-05 +outline-back-to-heading 12667 0.8362207570 6.601...e-05 +line-beginning-position 10333 0.7998346869 7.740...e-05 +org-agenda-format-item 279 0.7552402350 0.0027069542 +re-search-backward 16726 0.5694224969 3.404...e-05 +#+end_example + +** Profiling tags matching + +*** ng + +#+BEGIN_SRC elisp + (elp-profile 1 nil + (org-agenda-ng "~/org/main.org" + (tags "computer"))) +#+END_SRC + +#+RESULTS: +| Function | Times called | Total time | Average time | +|--------------------------------+--------------+--------------+--------------| +| mapcar | 4217 | 12.612716455 | 0.0029909216 | +| org-agenda-ng--agenda | 1 | 9.721410651 | 9.721410651 | +| org-get-tags-at | 1845 | 7.4793860389 | 0.0040538677 | +| org-up-heading-safe | 9361 | 6.4622674019 | 0.0006903394 | +| re-search-backward | 25001 | 5.3399866239 | 0.0002135909 | +| org-agenda-ng--filter-buffer | 1 | 4.874598854 | 4.874598854 | +| org-agenda-ng--tags-p | 1238 | 4.8067623430 | 0.0038826836 | +| org-agenda-ng--format-element | 607 | 3.6325626609 | 0.0059844524 | +| org-outline-level | 17484 | 1.0298924459 | 5.890...e-05 | +| org-add-props | 2074 | 0.8305549259 | 0.0004004604 | +| org-element-headline-parser | 607 | 0.2092664829 | 0.0003447553 | +| org-back-to-heading | 11813 | 0.1252112960 | 1.059...e-05 | +| outline-back-to-heading | 11813 | 0.1100693780 | 9.317...e-06 | +| org-end-of-subtree | 607 | 0.0721986340 | 0.0001189433 | +| outline-on-heading-p | 11813 | 0.0675261030 | 5.716...e-06 | +| outline-next-heading | 1239 | 0.0627980999 | 5.068...e-05 | +| re-search-forward | 3273 | 0.0612446620 | 1.871...e-05 | +| org-agenda-finalize-entries | 1 | 0.041846274 | 0.041846274 | +| buffer-substring-no-properties | 6329 | 0.0308716979 | 4.877...e-06 | +| line-end-position | 903 | 0.0280484950 | 3.106...e-05 | + +*** ng without inheritance + +#+BEGIN_SRC elisp + (elp-profile 1 nil + (org-agenda-ng "~/org/main.org" + (tags "computer"))) +#+END_SRC + +#+RESULTS: +| Function | Times called | Total time | Average time | +|--------------------------------+--------------+--------------+--------------| +| mapcar | 4217 | 12.580246839 | 0.0029832219 | +| org-agenda-ng--agenda | 1 | 8.777776059 | 8.777776059 | +| org-get-tags-at | 1845 | 8.2853503299 | 0.0044907047 | +| org-up-heading-safe | 9361 | 7.2710981889 | 0.0007767437 | +| re-search-backward | 25001 | 5.3360082060 | 0.0002134317 | +| org-agenda-ng--filter-buffer | 1 | 4.865602689 | 4.865602689 | +| org-agenda-ng--tags-p | 1238 | 4.7983754310 | 0.0038759090 | +| org-agenda-ng--format-element | 607 | 3.6273825100 | 0.0059759184 | +| org-outline-level | 17484 | 1.0284417919 | 5.882...e-05 | +| org-back-to-heading | 11813 | 0.9390534479 | 7.949...e-05 | +| org-split-string | 4940 | 0.833825087 | 0.0001687905 | +| string-match | 9102 | 0.8231629100 | 9.043...e-05 | +| org-element-headline-parser | 607 | 0.2034305819 | 0.0003351409 | +| outline-back-to-heading | 11813 | 0.1096120189 | 9.278...e-06 | +| org-end-of-subtree | 607 | 0.0710802559 | 0.0001171009 | +| outline-on-heading-p | 11813 | 0.0670029359 | 5.671...e-06 | +| outline-next-heading | 1239 | 0.0622323519 | 5.022...e-05 | +| re-search-forward | 3273 | 0.0603102519 | 1.842...e-05 | +| org-agenda-finalize-entries | 1 | 0.037286496 | 0.037286496 | +| buffer-substring-no-properties | 6329 | 0.0285818689 | 4.516...e-06 | + + +*** original + +#+BEGIN_SRC elisp + (elp-profile 1 nil + (with-current-buffer "main.org" +(org-tags-view nil "computer"))) +#+END_SRC + +#+RESULTS: +| Function | Times called | Total time | Average time | +|-----------------------------+--------------+--------------+--------------| +| org-tags-view | 1 | 2.620578129 | 2.620578129 | +| org-scan-tags | 1 | 1.448883817 | 1.448883817 | +| org-agenda-format-item | 607 | 0.9273893060 | 0.0015278242 | +| org-add-props | 2042 | 0.8877267209 | 0.0004347339 | +| org-agenda-finalize | 1 | 0.144506782 | 0.144506782 | +| re-search-forward | 2154 | 0.1367046650 | 6.346...e-05 | +| string-match | 8742 | 0.1002517259 | 1.146...e-05 | +| org-get-priority | 607 | 0.0961996220 | 0.0001584837 | +| org-agenda-align-tags | 1 | 0.095166495 | 0.095166495 | +| org-agenda-prepare | 1 | 0.081724472 | 0.081724472 | +| org-outline-level | 1246 | 0.0771033170 | 6.188...e-05 | +| org-agenda-finalize-entries | 1 | 0.071707404 | 0.071707404 | +| org-agenda-prepare-buffers | 1 | 0.057903921 | 0.057903921 | +| org-get-heading | 607 | 0.0517784369 | 8.530...e-05 | +| mapcar | 3738 | 0.0418641110 | 1.119...e-05 | +| org-agenda-highlight-todo | 607 | 0.0273123070 | 4.499...e-05 | +| mapconcat | 609 | 0.024743305 | 4.062...e-05 | +| sort | 2 | 0.02117069 | 0.010585345 | +| org-activate-plain-links | 132 | 0.0203558980 | 0.0001542113 | +| org-activate-bracket-links | 78 | 0.0198589680 | 0.0002546021 | ** Using =org-element-parse-buffer= @@ -1992,850 +2684,184 @@ string-match 4594 0.0064 mapcar 30 0.0041008740 0.0001366958 #+end_example -** Profiling position-based +** with/without ts.el -*** Macro +[2019-08-11 Sun 15:39] These results seem to show a minor performance improvement by using ~ts~, and the code is simpler. #+BEGIN_SRC elisp - (defmacro elp-profile (times &rest body) - (declare (indent defun)) - `(let ((prefixes '("org-" "string-" "s-" "buffer-" "append" "delq" "map" - "list" "car" "save-" "outline-" "delete-dups" - "sort" "line-" "nth" "concat" "char-to-string" - "rx-" "goto-" "when" "search-" "re-")) - output) - (dolist (prefix prefixes) - (elp-instrument-package prefix)) - (dotimes (x ,times) - ,@body) - (elp-results) - (elp-restore-all) - (point-min) - (forward-line 20) - (delete-region (point) (point-max)) - (setq output (buffer-substring-no-properties (point-min) (point-max))) - (kill-buffer) - (delete-window) - output)) + ;; (require 'ts) + + (org-ql--defpred ts-ts (&key from to _on) + ;; The underscore before `on' prevents "unused lexical variable" warnings, because we + ;; pre-process that argument in a macro before this function is called. + "Return non-nil if current entry has a timestamp in given period. + If no arguments are specified, return non-nil if entry has any + timestamp. + + If FROM, return non-nil if entry has a timestamp on or after + FROM. + + If TO, return non-nil if entry has a timestamp on or before TO. + + If ON, return non-nil if entry has a timestamp on date ON. + + FROM, TO, and ON should be strings parseable by + `parse-time-string' but may omit the time value." + ;; TODO: DRY this with the clocked predicate. + ;; NOTE: FROM and TO are actually expected to be Unix timestamps. The docstring is written + ;; for end users, for which the arguments are pre-processed by `org-ql-select'. + ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. + (cl-macrolet ((next-timestamp () + `(when (re-search-forward org-element--timestamp-regexp end-pos t) + (ts-parse-org (match-string 0)))) + (test-timestamps (pred-form) + `(cl-loop for next-ts = (next-timestamp) + while next-ts + thereis ,pred-form))) + (save-excursion + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (re-search-forward org-element--timestamp-regexp end-pos t)) + ((and from to) (test-timestamps (and (ts<= from next-ts) + (ts<= next-ts to)))) + (from (test-timestamps (ts<= from next-ts))) + (to (test-timestamps (ts<= next-ts to)))))))) + #+END_SRC - -*** orig - -Make sure to kill any existing agenda buffers first. +*** :from #+BEGIN_SRC elisp - (elp-profile 1 (org-agenda-list nil nil 'week)) -#+END_SRC - -#+RESULTS: -#+begin_example -org-agenda-list 1 9.693596196 9.693596196 -org-agenda-get-day-entries 56 8.630330659 0.1541130474 -org-agenda-get-scheduled 56 6.6207980570 0.1182285367 -org-is-habit-p 2792 2.2907458449 0.0008204677 -org-entry-get 2798 2.287390186 0.0008175090 -org-agenda--timestamp-to-absolute 7708 2.0970420100 0.0002720604 -org-agenda-get-deadlines 56 1.6941886389 0.0302533685 -org-at-planning-p 4399 1.3993312159 0.0003181021 -org--property-local-values 2793 1.2699226760 0.0004546805 -org-get-property-block 2794 1.2182695930 0.0004360306 -org-time-string-to-absolute 7708 1.1513844880 0.0001493752 -org-inlinetask-in-task-p 6969 1.139932302 0.0001635718 -org-parse-time-string 7880 1.0635759220 0.0001349715 -org-closest-date 3864 1.0383435800 0.0002687224 -re-search-forward 15199 0.9607921779 6.321...e-05 -org-back-to-heading 12667 0.8564486210 6.761...e-05 -outline-back-to-heading 12667 0.8362207570 6.601...e-05 -line-beginning-position 10333 0.7998346869 7.740...e-05 -org-agenda-format-item 279 0.7552402350 0.0027069542 -re-search-backward 16726 0.5694224969 3.404...e-05 -#+end_example - -*** ng-funcall - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--test-agenda-today)) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 121 0.1296645480 0.0010716078 -org-agenda-ng--test-agenda-today 5 0.086714029 0.0173428058 -org-agenda-ng--agenda 5 0.086584611 0.0173169222 -org-agenda-ng--format-element 75 0.0307461019 0.0004099480 -org-agenda-ng--filter-buffer 5 0.027136826 0.0054273652 -org-agenda-ng--date-p 455 0.0213037090 4.682...e-05 -org-element-headline-parser 75 0.016251755 0.0002166900 -org-get-tags-at 75 0.008959605 0.0001194614 -org-agenda-ng--add-faces 75 0.0072381410 9.650...e-05 -org-element-timestamp-interpreter 150 0.0069832960 4.655...e-05 -org-entry-get 290 0.0061220340 2.111...e-05 -org-up-heading-safe 210 0.0057036860 2.716...e-05 -org-agenda-finalize-entries 5 0.005372899 0.0010745798 -org-element-timestamp-parser 150 0.0050518689 3.367...e-05 -org-entry-properties 290 0.0049517209 1.707...e-05 -org-agenda-ng--add-deadline-face 75 0.0039273909 5.236...e-05 -org-element--get-time-properties 75 0.0039059429 5.207...e-05 -org-back-to-heading 725 0.0037793259 5.212...e-06 -org-parse-time-string 300 0.0032196259 1.073...e-05 -org-agenda-ng--add-scheduled-face 75 0.0031410580 4.188...e-05 -#+end_example - -*** ng-flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--test-agenda-today)) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 121 0.1292609089 0.0010682719 -org-agenda-ng--test-agenda-today 5 0.0860146149 0.017202923 -org-agenda-ng--agenda 5 0.0858901769 0.0171780353 -org-agenda-ng--format-element 75 0.0308815090 0.0004117534 -org-agenda-ng--filter-buffer 5 0.026709027 0.0053418054 -org-agenda-ng--date-p 455 0.0210552310 4.627...e-05 -org-element-headline-parser 75 0.016209908 0.0002161321 -org-get-tags-at 75 0.008953666 0.0001193822 -org-agenda-ng--add-faces 75 0.0072834109 9.711...e-05 -org-element-timestamp-interpreter 150 0.0068781430 4.585...e-05 -org-entry-get 290 0.0060815609 2.097...e-05 -org-up-heading-safe 210 0.005708647 2.718...e-05 -org-agenda-finalize-entries 5 0.005201221 0.0010402442 -org-element-timestamp-parser 150 0.005191617 3.461078e-05 -org-entry-properties 290 0.0048787450 1.682...e-05 -org-element--get-time-properties 75 0.004112675 5.483...e-05 -org-agenda-ng--add-deadline-face 75 0.0039314910 5.241...e-05 -org-back-to-heading 725 0.0037559990 5.180...e-06 -org-agenda-ng--add-scheduled-face 75 0.0031766149 4.235...e-05 -org-parse-time-string 300 0.0031740200 1.058...e-05 -#+end_example - -** Profiling =org-trust-scanner-tags= - -[2018-05-10 Thu 12:59] Turned on =org-trust-scanner-tags=, going to try profiling again: - -#+BEGIN_SRC elisp - ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - ;; (tags "world"))) - - (elp-profile 10 nil (org-agenda-ng org-agenda-files - (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| org-agenda-ng--agenda | 10 | 44.092598282 | 4.4092598282 | -| mapcar | 282 | 40.234516707 | 0.1426755911 | -| org-agenda-ng--filter-buffer | 80 | 26.895492471 | 0.3361936558 | -| org-element-headline-parser | 3980 | 10.387614362 | 0.0026099533 | -| org-agenda-finalize-entries | 10 | 9.194458252 | 0.9194458252 | -| org-agenda-ng--tags-p | 70250 | 8.1897379849 | 0.0001165799 | -| org-agenda-ng--format-element | 3980 | 6.5944325679 | 0.0016568926 | -| outline-next-heading | 70320 | 6.1190180490 | 8.701...e-05 | -| re-search-forward | 97050 | 5.8706467829 | 6.049...e-05 | -| org-get-tags-at | 74230 | 5.4078158059 | 7.285...e-05 | -| org-super-agenda--filter-finalize-entries | 10 | 5.2320123400 | 0.5232012340 | -| org-super-agenda--group-items | 10 | 5.1260959210 | 0.5126095921 | -| org-super-agenda--group-dispatch | 130 | 5.119333624 | 0.0393794894 | -| sort | 20 | 3.8204368569 | 0.1910218428 | -| org-element--parse-objects | 6180 | 3.5386578929 | 0.0005725983 | -| org-is-habit-p | 5970 | 3.2497755920 | 0.0005443510 | -| org-entry-get | 5970 | 3.2347964049 | 0.0005418419 | -| org--property-local-values | 5970 | 3.1796357319 | 0.0005326023 | -| org-get-property-block | 5970 | 3.0767919680 | 0.0005153755 | -| org-entries-lessp | 20020 | 2.6563960079 | 0.0001326871 | - -Now trying again without it: - -#+BEGIN_SRC elisp - ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - ;; (tags "world"))) - - (elp-profile 10 nil (org-agenda-ng org-agenda-files - (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| mapcar | 1791 | 57.096304538 | 0.0318795670 | -| org-agenda-ng--agenda | 10 | 54.232133506 | 5.4232133505 | -| org-agenda-ng--filter-buffer | 80 | 30.065167040 | 0.3758145880 | -| org-get-tags-at | 74230 | 13.840202495 | 0.0001864502 | -| org-agenda-ng--format-element | 3980 | 13.429297797 | 0.0033741954 | -| org-element-headline-parser | 3980 | 12.771776652 | 0.0032089891 | -| org-agenda-finalize-entries | 10 | 9.1439433990 | 0.9143943399 | -| org-agenda-ng--tags-p | 70250 | 9.0249653730 | 0.0001284692 | -| org-super-agenda--filter-finalize-entries | 10 | 7.300515859 | 0.7300515859 | -| outline-next-heading | 70320 | 7.2384435649 | 0.0001029357 | -| org-super-agenda--group-items | 10 | 4.918585855 | 0.4918585855 | -| org-super-agenda--group-dispatch | 130 | 4.9125893509 | 0.0377891488 | -| re-search-forward | 101020 | 4.6294823850 | 4.582...e-05 | -| org-up-heading-safe | 7370 | 4.4629885620 | 0.0006055615 | -| org-is-habit-p | 5960 | 4.2772351910 | 0.0007176569 | -| org-entry-get | 5960 | 4.2595350800 | 0.0007146870 | -| org-super-agenda--group-tag | 50 | 3.8942044929 | 0.0778840898 | -| re-search-backward | 26150 | 3.3660083490 | 0.0001287192 | -| org--property-local-values | 5960 | 3.1793476329 | 0.0005334475 | -| org-get-property-block | 5960 | 3.0662425979 | 0.0005144702 | - -Wow, using =org-trust-scanner-tags= saves a /lot/ of time. - -** Profiling flet across all agenda files - -*** Without flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files org-agenda-files - :pred (lambda () - (and (org-agenda-ng--todo-p) - (or (org-agenda-ng--date-p :deadline '<= (org-today)) - (org-agenda-ng--date-p :scheduled '<= (org-today))) - (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 711 26.910164986 0.0378483333 -org-agenda-ng--agenda 5 21.012501837 4.2025003674 -org-agenda-ng--filter-buffer 40 13.751964650 0.3437991162 -org-agenda-ng--todo-p 37080 5.8788306440 0.0001585445 -org-agenda-ng--format-element 1180 4.5712275970 0.0038739216 -org-get-todo-state 37080 4.1661659069 0.0001123561 -org-agenda-ng--date-p 21595 4.1442710769 0.0001919088 -org-entry-get 22730 2.8275069239 0.0001243953 -org-entry-properties 21595 2.6558403739 0.0001229840 -outline-next-heading 34625 2.0894695999 6.034...e-05 -org-element-headline-parser 1180 1.9110445780 0.0016195293 -re-search-forward 42280 1.6994989150 4.019...e-05 -org-agenda-ng--add-faces 1180 1.6172592580 0.0013705586 -org-agenda-ng--add-scheduled-face 1180 1.607386145 0.0013621916 -org-get-tags-at 1180 1.1521010509 0.0009763568 -org-back-to-heading 64530 1.1005834200 1.705...e-05 -org-up-heading-safe 2360 1.0182265390 0.0004314519 -outline-back-to-heading 64530 1.0086056729 1.563...e-05 -org-parse-time-string 7560 0.8314918499 0.0001099856 -org-time-string-to-absolute 3780 0.8277485280 0.0002189810 -#+end_example - - -*** With flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files org-agenda-files - :pred (lambda () - (and (todo) - (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 711 25.608392569 0.0360174297 -org-agenda-ng--agenda 5 24.019318793 4.8038637586 -org-agenda-ng--filter-buffer 40 14.160293256 0.3540073313 -org-agenda-ng--date-p 21595 4.2111783960 0.0001950071 -org-agenda-finalize-entries 5 4.0930243110 0.8186048622 -org-super-agenda--filter-finalize-entries 5 3.937522006 0.7875044012 -org-agenda-ng--todo-p 37080 3.5687476730 9.624...e-05 -org-get-todo-state 37080 3.4737076600 9.368...e-05 -outline-next-heading 34625 3.4689080650 0.0001001850 -re-search-forward 42280 3.0743315830 7.271...e-05 -org-agenda-ng--format-element 1180 2.9511605820 0.0025009835 -org-element-headline-parser 1180 2.6757063699 0.0022675477 -org-super-agenda--group-items 5 2.187362092 0.4374724183 -org-super-agenda--group-dispatch 70 2.184685662 0.0312097951 -org-entry-get 22730 2.0711872869 9.112...e-05 -org-entry-properties 21595 1.8958912070 8.779...e-05 -org-super-agenda--group-tag 25 1.8498977799 0.0739959111 -org-element-timestamp-parser 3785 1.8234333229 0.0004817525 -org-parse-time-string 7560 1.7121709579 0.0002264776 -org-element--get-time-properties 1180 1.1814058020 0.0010011913 -#+end_example - -** Profiling flet on a single file - -This shows that the difference between them, if any, is so small as to be irrelevant. The convenience and clarity are a big win. - -*** Without flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files "~/org/main.org" - :pred (lambda () - (and (org-agenda-ng--todo-p) - (or (org-agenda-ng--date-p :deadline '<= (org-today)) - (org-agenda-ng--date-p :scheduled '<= (org-today))) - (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 526 3.7766218089 0.0071798893 -org-agenda-ng--agenda 5 2.75718831 0.551437662 -org-agenda-ng--filter-buffer 5 1.402551392 0.2805102784 -org-agenda-ng--format-element 265 0.8864161399 0.0033449665 -org-get-tags-at 265 0.7896260759 0.0029797210 -org-up-heading-safe 1150 0.7589292910 0.0006599385 -re-search-backward 3700 0.5956338739 0.0001609821 -org-agenda-ng--todo-p 6690 0.5781650060 8.642...e-05 -org-get-todo-state 6690 0.5603983020 8.376...e-05 -org-agenda-ng--date-p 5940 0.5209897369 8.770...e-05 -org-entry-get 6195 0.4158440950 6.712...e-05 -org-entry-properties 5940 0.3640524090 6.128...e-05 -org-element-headline-parser 265 0.2810144710 0.0010604319 -outline-next-heading 6195 0.2485497380 4.012...e-05 -org-back-to-heading 14565 0.1957209180 1.343...e-05 -re-search-forward 7850 0.1927130979 2.454...e-05 -outline-back-to-heading 14565 0.1751091780 1.202...e-05 -org-outline-level 2300 0.1680958539 7.308...e-05 -org-agenda-finalize-entries 5 0.1610422239 0.0322084448 -org-super-agenda--filter-finalize-entries 5 0.132423043 0.0264846085 -#+end_example - - -*** With flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files "~/org/main.org" - :pred (lambda () - (and (todo) - (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 526 3.7898506779 0.0072050393 -org-agenda-ng--agenda 5 2.7695176850 0.5539035370 -org-agenda-ng--filter-buffer 5 1.414347774 0.2828695548 -org-agenda-ng--format-element 265 0.8871611419 0.0033477778 -org-get-tags-at 265 0.7891641319 0.0029779778 -org-up-heading-safe 1150 0.7581951110 0.0006593000 -re-search-backward 3700 0.5948686769 0.0001607753 -org-agenda-ng--todo-p 6690 0.5840980579 8.730...e-05 -org-get-todo-state 6690 0.5666448919 8.470...e-05 -org-agenda-ng--date-p 5940 0.5196037069 8.747...e-05 -org-entry-get 6195 0.4144106150 6.689...e-05 -org-entry-properties 5940 0.3640680380 6.129...e-05 -org-element-headline-parser 265 0.2810144920 0.0010604320 -outline-next-heading 6195 0.2495287770 4.027...e-05 -org-back-to-heading 14565 0.1959557380 1.345...e-05 -re-search-forward 7850 0.1933439489 2.462...e-05 -outline-back-to-heading 14565 0.1753121230 1.203...e-05 -org-outline-level 2300 0.1676228200 7.287...e-05 -org-agenda-finalize-entries 5 0.1607656930 0.0321531386 -org-super-agenda--filter-finalize-entries 5 0.1316961509 0.0263392301 -#+end_example - -** Profiling tags matching - -*** ng - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (org-agenda-ng "~/org/main.org" - (tags "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|--------------------------------+--------------+--------------+--------------| -| mapcar | 4217 | 12.612716455 | 0.0029909216 | -| org-agenda-ng--agenda | 1 | 9.721410651 | 9.721410651 | -| org-get-tags-at | 1845 | 7.4793860389 | 0.0040538677 | -| org-up-heading-safe | 9361 | 6.4622674019 | 0.0006903394 | -| re-search-backward | 25001 | 5.3399866239 | 0.0002135909 | -| org-agenda-ng--filter-buffer | 1 | 4.874598854 | 4.874598854 | -| org-agenda-ng--tags-p | 1238 | 4.8067623430 | 0.0038826836 | -| org-agenda-ng--format-element | 607 | 3.6325626609 | 0.0059844524 | -| org-outline-level | 17484 | 1.0298924459 | 5.890...e-05 | -| org-add-props | 2074 | 0.8305549259 | 0.0004004604 | -| org-element-headline-parser | 607 | 0.2092664829 | 0.0003447553 | -| org-back-to-heading | 11813 | 0.1252112960 | 1.059...e-05 | -| outline-back-to-heading | 11813 | 0.1100693780 | 9.317...e-06 | -| org-end-of-subtree | 607 | 0.0721986340 | 0.0001189433 | -| outline-on-heading-p | 11813 | 0.0675261030 | 5.716...e-06 | -| outline-next-heading | 1239 | 0.0627980999 | 5.068...e-05 | -| re-search-forward | 3273 | 0.0612446620 | 1.871...e-05 | -| org-agenda-finalize-entries | 1 | 0.041846274 | 0.041846274 | -| buffer-substring-no-properties | 6329 | 0.0308716979 | 4.877...e-06 | -| line-end-position | 903 | 0.0280484950 | 3.106...e-05 | - -*** ng without inheritance - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (org-agenda-ng "~/org/main.org" - (tags "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|--------------------------------+--------------+--------------+--------------| -| mapcar | 4217 | 12.580246839 | 0.0029832219 | -| org-agenda-ng--agenda | 1 | 8.777776059 | 8.777776059 | -| org-get-tags-at | 1845 | 8.2853503299 | 0.0044907047 | -| org-up-heading-safe | 9361 | 7.2710981889 | 0.0007767437 | -| re-search-backward | 25001 | 5.3360082060 | 0.0002134317 | -| org-agenda-ng--filter-buffer | 1 | 4.865602689 | 4.865602689 | -| org-agenda-ng--tags-p | 1238 | 4.7983754310 | 0.0038759090 | -| org-agenda-ng--format-element | 607 | 3.6273825100 | 0.0059759184 | -| org-outline-level | 17484 | 1.0284417919 | 5.882...e-05 | -| org-back-to-heading | 11813 | 0.9390534479 | 7.949...e-05 | -| org-split-string | 4940 | 0.833825087 | 0.0001687905 | -| string-match | 9102 | 0.8231629100 | 9.043...e-05 | -| org-element-headline-parser | 607 | 0.2034305819 | 0.0003351409 | -| outline-back-to-heading | 11813 | 0.1096120189 | 9.278...e-06 | -| org-end-of-subtree | 607 | 0.0710802559 | 0.0001171009 | -| outline-on-heading-p | 11813 | 0.0670029359 | 5.671...e-06 | -| outline-next-heading | 1239 | 0.0622323519 | 5.022...e-05 | -| re-search-forward | 3273 | 0.0603102519 | 1.842...e-05 | -| org-agenda-finalize-entries | 1 | 0.037286496 | 0.037286496 | -| buffer-substring-no-properties | 6329 | 0.0285818689 | 4.516...e-06 | - - -*** original - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (with-current-buffer "main.org" -(org-tags-view nil "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-----------------------------+--------------+--------------+--------------| -| org-tags-view | 1 | 2.620578129 | 2.620578129 | -| org-scan-tags | 1 | 1.448883817 | 1.448883817 | -| org-agenda-format-item | 607 | 0.9273893060 | 0.0015278242 | -| org-add-props | 2042 | 0.8877267209 | 0.0004347339 | -| org-agenda-finalize | 1 | 0.144506782 | 0.144506782 | -| re-search-forward | 2154 | 0.1367046650 | 6.346...e-05 | -| string-match | 8742 | 0.1002517259 | 1.146...e-05 | -| org-get-priority | 607 | 0.0961996220 | 0.0001584837 | -| org-agenda-align-tags | 1 | 0.095166495 | 0.095166495 | -| org-agenda-prepare | 1 | 0.081724472 | 0.081724472 | -| org-outline-level | 1246 | 0.0771033170 | 6.188...e-05 | -| org-agenda-finalize-entries | 1 | 0.071707404 | 0.071707404 | -| org-agenda-prepare-buffers | 1 | 0.057903921 | 0.057903921 | -| org-get-heading | 607 | 0.0517784369 | 8.530...e-05 | -| mapcar | 3738 | 0.0418641110 | 1.119...e-05 | -| org-agenda-highlight-todo | 607 | 0.0273123070 | 4.499...e-05 | -| mapconcat | 609 | 0.024743305 | 4.062...e-05 | -| sort | 2 | 0.02117069 | 0.010585345 | -| org-activate-plain-links | 132 | 0.0203558980 | 0.0001542113 | -| org-activate-bracket-links | 78 | 0.0198589680 | 0.0002546021 | - -** More profiling - -[2018-05-10 Thu 15:02] I think these are decent improvements. - -#+BEGIN_SRC elisp - (elp-profile 1 nil (org-agenda-ng "~/org/main.org" - (or (habit) - (and (or (date '= (org-today)) - (deadline '<=) - (scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))) - (and (todo "DONE" "CANCELLED") - (closed '= (org-today)))))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------+--------------+--------------+--------------| -| mapcar | 164 | 1.5004585290 | 0.0091491373 | -| org-agenda-ng--agenda | 1 | 1.348231247 | 1.348231247 | -| org-agenda-ng--filter-buffer | 1 | 1.1391189879 | 1.1391189879 | -| org-agenda-ng--date-plain-p | 1267 | 0.6198571040 | 0.0004892321 | -| org-entry-get | 3983 | 0.2979337370 | 7.480...e-05 | -| org-is-habit-p | 1365 | 0.2049101109 | 0.0001501172 | -| org--property-local-values | 1365 | 0.1940614150 | 0.0001421695 | -| org-agenda-ng--habit-p | 1272 | 0.1911009179 | 0.0001502365 | -| org-agenda-ng--format-element | 52 | 0.177965411 | 0.0034224117 | -| org-get-property-block | 1365 | 0.1760004519 | 0.0001289380 | -| org-get-tags-at | 52 | 0.1362824969 | 0.0026208172 | -| org-agenda-ng--date-p | 3880 | 0.1351176629 | 3.482...e-05 | -| org-up-heading-safe | 226 | 0.1276747609 | 0.0005649325 | -| re-search-backward | 2028 | 0.1144211070 | 5.642...e-05 | -| org-entry-properties | 2618 | 0.0848660999 | 3.241...e-05 | -| org-agenda-ng--todo-p | 1319 | 0.081952653 | 6.213...e-05 | -| org-get-todo-state | 1319 | 0.0796836810 | 6.041...e-05 | -| re-search-forward | 3754 | 0.0739803739 | 1.970...e-05 | -| org-inlinetask-in-task-p | 1365 | 0.0657829330 | 4.819...e-05 | -| org-agenda-ng--scheduled-p | 1247 | 0.0619497850 | 4.967...e-05 | - -** Intersecting query results - -An idea that /might/ be helpful for performance in /some/ cases, depending on the query, the data, and whether the query has a preamble. But it looks like it would very rarely be helpful. - -#+BEGIN_SRC elisp - (cl-defun org-ql-agenda-intersection (buffers-files queries &key entries sort buffer narrow super-groups) - "Like `org-ql-agenda', but intersects multiple queries." - (declare (indent defun)) - (let* ((org-ql-cache (ht)) - (entries (->> queries - (--map (org-ql-select buffers-files - it - :action 'element-with-markers - :narrow narrow - :sort sort)) - (-reduce #'-intersection)))) - (org-ql-agenda--agenda buffers-files queries - :entries entries :super-groups super-groups))) - - (bench-multi-lexical :times 1 - :forms (("intersection" (let ((org-use-tag-inheritance nil)) - (org-ql-agenda-intersection (org-agenda-files) - '((todo "TODO") - (tags "Emacs")) - :sort '(priority deadline) - :super-groups org-super-agenda-groups))) - ("normal" (let ((org-use-tag-inheritance nil)) - (org-ql-agenda (org-agenda-files) - (and (todo "TODO") - (tags "Emacs")) - :sort (priority deadline) - :super-groups org-super-agenda-groups))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------+--------------------+---------------+----------+------------------| -| normal | 3.70 | 0.233147 | 0 | 0 | -| intersection | slowest | 0.862512 | 0 | 0 | - -*** Alternative approach - -[2019-09-01 Sun 08:17] This is very experimental, but the results are surprising. When the action function returns a fairly simple list, the intersection is very slightly faster. When returning full elements, the intersection is much slower, so that it more than doubles the runtime. I wonder if the element list comparison is short-circuiting, or if it looks at the whole lists, because it seems like it shouldn't take more than 4-5 list elements before it realizes that two lists don't match. - -Anyway, looks like this approach isn't viable, at least not without a much more complicated implementation, which probably wouldn't be worth it. - -#+BEGIN_SRC elisp - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - ;; NOTE: Careful to use the same files and action in each one. I duplicated - ;; the variable in each form to make individual testing easier. - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (let ((org-ql-cache (ht)) - (action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn)))) - ("Testing" (let* ((org-ql-cache (ht)) - (files '("~/org/main.org")) - (action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| Testing | 1.15 | 0.248376 | 0 | 0 | -| normal | slowest | 0.284897 | 0 | 0 | - -#+BEGIN_SRC elisp - -;; With caching enabled - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn))) - ("Testing" (let* ((files '("~/org/main.org")) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 13.72 | 0.002311 | 0 | 0 | -| Testing | slowest | 0.031707 | 0 | 0 | - -Using full views: - -#+BEGIN_SRC elisp - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (bench-multi-lexical :times 1 - :forms (("normal" (->> (let ((org-ql-cache (ht)) - (files '("~/org/main.org"))) - (org-ql-search files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))))))) - ("Testing" (let* ((org-ql-cache (ht)) - (files '("~/org/main.org")) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action 'element-with-markers)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action 'element-with-markers))) - (final-results (seq-intersection and-results - (->> or-results - -uniq)))) - (org-ql-agenda--agenda nil nil - :entries final-results) - - ))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 1.74 | 0.534742 | 0 | 0 | -| Testing | slowest | 0.931897 | 0 | 0 | - -Just gathering results, but using elements: - -#+BEGIN_SRC elisp - (let* ((action-fn 'element-with-markers) - (files '("~/org/main.org"))) - ;; NOTE: Careful to use the same files and action in each one. I duplicated - ;; the variable in each form to make individual testing easier. - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (let ((org-ql-cache (ht))) - (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn)))) - ("Testing" (let* ((org-ql-cache (ht)) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 2.27 | 0.314218 | 0 | 0 | -| Testing | slowest | 0.714587 | 0 | 0 | - - -** [2019-08-29 Thu 06:24] Benchmarking org-ql compared to re-search-forward for getting headings in buffer -:PROPERTIES: -:ID: fcc09229-ed24-42eb-a1fd-31d8f7d4c8d5 -:END: - -Minimal difference, and that's a very large file, too. On smaller files it's thousandths of a second. - -#+BEGIN_SRC elisp - (with-current-buffer (find-buffer-visiting "~/org/inbox.org") - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("org-ql" (org-ql-select (current-buffer) - '(level 1) - :action '(progn - (font-lock-ensure (line-beginning-position) (line-end-position)) - (cons (org-get-heading t) (point))))) - ("re-search-forward" (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop while (re-search-forward (rx bol "*" (1+ blank)) nil t) - do (font-lock-ensure (line-beginning-position) (line-end-position)) - collect (cons (org-get-heading t) (match-beginning 0)))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------+--------------------+---------------+----------+------------------| -| re-search-forward | 1.17 | 0.520375 | 0 | 0 | -| org-ql | slowest | 0.608281 | 0 | 0 | - -** Caching of inherited tags - -[2019-09-05 Thu 07:59] Implemented a per-buffer tags cache that seems to significantly speed up tags queries that use tag inheritance. It persists as long as the buffer remains unmodified, and it's usable from any code as a single function that automatically uses caching. It also returns inherited tags and local tags separately, which could be useful for having separate selectors, one for inherited tags, one for local tags, and one for both. - -#+BEGIN_SRC elisp - (defvar org-ql-tags-cache (ht) - "Per-buffer tags cache. - Keyed by buffer. Each value is a cons of the buffer's modified - tick, and another hash table keyed on buffer position, whose - values are a list of two lists, inherited tags and local tags, as - strings.") - - (defun org-ql--tags-at (position) - "Return tags for POSITION in current buffer. - Returns cons (INHERITED-TAGS . LOCAL-TAGS)." - ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables - ;; bound in the else clause, so destructured variables that are non-nil, - ;; like found caches, are not available in the else clause. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) - (modified-tick (car buffer-cache)) - (tags-cache (cdr buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cached-result (gethash position tags-cache))) - ;; Found in cache: return them. - (pcase cached-result - ('org-ql-nil nil) - (_ cached-result)) - ;; Not found in cache: get tags and cache them. - (let* ((local-tags (or (org-get-tags position 'local) - 'org-ql-nil)) - (inherited-tags (or (save-excursion - (when (org-up-heading-safe) - (-let* (((inherited local) (org-ql--tags-at (point))) - (inherited-tags (when (or inherited local) - (cond ((and (listp inherited) - (listp local)) - (append inherited local)) - ((cond ((listp inherited) inherited) - ((listp local) local))))))) - (when inherited-tags - (->> inherited-tags -non-nil -uniq))))) - 'org-ql-nil)) - (all-tags (list inherited-tags local-tags))) - ;; Check caches again, because they may have been set now. - ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? - (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) - modified-tick (car buffer-cache) - tags-cache (cdr buffer-cache) - buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cond ((or (not buffer-cache) - (not buffer-unmodified-p)) - ;; Buffer-local tags cache empty or invalid: make new one. - (puthash (current-buffer) - (cons (buffer-modified-tick) - (let ((table (make-hash-table))) - (puthash position all-tags table) - table)) - org-ql-tags-cache) - ;; Return tags, not the cons put on the buffer-cache. - all-tags) - ;; Buffer-local tags cache found, but no result: store this one. - (t (puthash position all-tags tags-cache)))))) - - (org-ql--defpred tags-cached (&rest tags) - "Return non-nil if current heading has one or more of TAGS (a list of strings)." - ;; TODO: Try to use `org-make-tags-matcher' to improve performance. It would be nice to not have - ;; to run `org-get-tags' for every heading, especially with inheritance. - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((inherited local) (org-ql--tags-at (point)))) - (cl-typecase tags - (null (or (tags-p inherited) - (tags-p local))) - (otherwise (or (when (tags-p inherited) - (seq-intersection tags inherited)) - (when (tags-p local) - (seq-intersection tags local)))))))) -#+END_SRC - -Benchmark results: - -#+BEGIN_SRC elisp - (let* ((buffers '("~/org/main.org")) - (tags '("Emacs"))) - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("uncached" (let ((org-ql-cache (ht))) - (org-ql-select buffers - `(tags ,@tags)))) - ("cached" (let ((org-ql-cache (ht)) - (org-ql-tags-cache (ht))) - (org-ql-select buffers - `(tags-cached ,@tags))))))) + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("old ts" (org-ql "~/org/inbox.org" + (ts :from "2017-01-01"))) + ("ts.el ts" (org-ql "~/org/inbox.org" + (ts-ts :from "2017-01-01"))))) #+END_SRC #+RESULTS: | Form | x faster than next | Total runtime | # of GCs | Total GC runtime | |----------+--------------------+---------------+----------+------------------| -| cached | 6.51 | 0.519871 | 0 | 0 | -| uncached | slowest | 3.386679 | 0 | 0 | +| ts.el ts | 1.32 | 1.299966 | 0 | 0 | +| old ts | slowest | 1.713027 | 0 | 0 | + +*** :on + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("old ts" (org-ql "~/org/inbox.org" + (ts :on "2019-05-14"))) + ("ts.el ts" (org-ql "~/org/inbox.org" + (ts-ts :on "2019-05-14"))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------+--------------------+---------------+----------+------------------| +| ts.el ts | 1.17 | 0.557281 | 0 | 0 | +| old ts | slowest | 0.652149 | 0 | 0 | + +*** :to + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("old ts" (org-ql "~/org/inbox.org" + (ts :to "2019-01-01"))) + ("ts.el ts" (org-ql "~/org/inbox.org" + (ts-ts :to "2019-01-01"))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------+--------------------+---------------+----------+------------------| +| ts.el ts | 1.01 | 1.300084 | 0 | 0 | +| old ts | slowest | 1.312208 | 0 | 0 | + +*** Without timestamp argument + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 1 :ensure-equal t + :forms (("old ts" (org-ql "~/org/inbox.org" + (ts))) + ("ts.el ts" (org-ql "~/org/inbox.org" + (ts-ts))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------+--------------------+---------------+----------+------------------| +| ts.el ts | 1.14 | 2.251801 | 0 | 0 | +| old ts | slowest | 2.560280 | 0 | 0 | + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 20 :ensure-equal t + :forms (("old ts" (org-ql "~/src/emacs/org-ql/tests/data.org" + (ts))) + ("ts.el ts" (org-ql "~/src/emacs/org-ql/tests/data.org" + (ts-ts))))) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------+--------------------+---------------+----------+------------------| +| ts.el ts | 1.05 | 0.103714 | 0 | 0 | +| old ts | slowest | 0.108663 | 0 | 0 | + +* References +:PROPERTIES: +:TOC: :include descendants :depth 1 +:END: +:CONTENTS: +- [[#github---ndwarshuisorg-sql-sql-backend-for-emacs-org-mode][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] +- [[#john-kitchin-on-rewriting-the-org-agenda-code][John Kitchin on rewriting the Org agenda code]] +- [[#nicolas-goazious-org-element-cache-implementation][Nicolas Goaziou's org-element cache implementation]] +- [[#uniform-structured-syntax-metaprogramming-and-run-time-compilation][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] +:END: + +** [[https://github.com/ndwarshuis/org-sql][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] + +[2020-01-04 Sat 09:03] + +** [[gnus:gmane.emacs.orgmode#CAJ51EToLCm5zDLKu8XeuqEWrLhHZF+OoNkviPSivZbFttzF8=A@mail.gmail.com][John Kitchin on rewriting the Org agenda code]] :Emacs:Org: + +[2019-10-28 Mon 08:28] Originally from [[id:90a68535-2403-4ba9-a117-60be1862628f][this entry in my notes]]. + +#+BEGIN_QUOTE +From: John Kitchin +Subject: Re: [Orgmode] Slow speed of week and month views +Newsgroups: gmane.emacs.orgmode +To: Karl Voit +Cc: "emacs-orgmode@gnu.org" +Date: Sat, 5 Aug 2017 18:17:09 -0400 (4 hours, 11 minutes, 38 seconds ago) + +I can think of two possibilities for a future approach (besides a deep dive on profiling the current elisp to improve the speed there). They both involve some substantial coding though, and would probably add dependencies. I am curious what anyone things about these, or if there are other ideas. + +One is to use the new dynamic module capability to write an org parser in C, or a dedicated agenda function, which would presumably be faster than in elisp. This seems hard, and for me would certainly be a multiyear project I am sure! The downside of this is the need to compile the module. I don't know how easy it would be to make this work across platforms with the relatively easy install org-mode currently has. This could have a side benefit though of a c-lib that could be used by others to expand where org-mode is used. + +The other way that might work is to rely more heavily on a cached version of the files, perhaps in a different format than elisp, that is faster to work with. The approach I have explored in this is to index org files into a sqlite database. The idea then would be to generate the agenda from a sql query. I use something like this already to "find stuff in orgmode anywhere". One of the reasons I wrote this is the org-agenda list of files isn't practical for me because my files are so scattered on my file system. I had a need to be able to find TODOs in research projects in a pretty wide range of locations. + +The code I use is at https://github.com/jkitchin/scimax/blob/master/org-db.el, and from one database I can find headlines, contacts, locations, TODO headlines across my file system, all the files that contain a particular link, and my own recent org files. This approach relies on emacsql, and a set of hook functions to update the database whenever a file is changed. It is not robust, e.g. the file could be out of sync with the db if it is modified outside emacs, but this works well enough for me so far. Updated files get reindexed whenever emacs is idle. It was a compromise on walking the file system all the time or daily, or trying to use inotify and you can always run a command to prune/sync all the files any time you want. + +sqlite is ok, but with emacsql you cannot put strings in it directly (at least when I wrote the org-db code), which has limited it for full-text search so far. Also with text, the db got up to about 0.5 GB in size, and started slowing down. So it doesn't have text in it for now. It has all the other limitations of sqlite too, limited support for locking, single process.... + +I am moderately motivated to switch from sqlite to MongoDB, but the support for Mongo in emacs is pretty crummy (I tried writing a few traditional interfaces, but the performance was not that good, and limited since Mongo uses bson, and it is just not the same as json!). Why Mongo? Mostly because the Mongo query language is basically json and easy to generate in Emacs, unlike sql. Also, it is flexible and easy to adapt to new things, e.g. indexing src-blocks or tables or whatever org-element you want. (And I want to use Mongo for something else too ;). Obviously these all add dependencies, and might not be suitable for the core org-mode distribution. But I do think it is important to think about ways to scale org-mode while maintaining compatibility with the core. + +The main point of the database was to get a query language, persistence and good performance. I have also used caches to speed up using bibtex files, and my org-contacts with reasonable performance. These have been all elisp, with no additional dependencies. Maybe one could do something similar to keep an agenda cache that is persistent and updated via hook functions. + +Thoughts? + +John +#+END_QUOTE +:PROPERTIES: +:archive.is: http://archive.is/33R9M +:END: + ++ [[https://github.com/m00natic/cl-fdbq][GitHub - m00natic/cl-fdbq: SQL-like operations over fixed field DBs]] + +** Nicolas Goaziou's =org-element= cache implementation + +[2020-01-04 Sat 08:31] https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el#L4817 I guess I haven't been keeping up, because I'm not sure when exactly he made or committed this, or what his plans for it are. It's currently disabled by default. + +** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] * Testing @@ -3083,6 +3109,41 @@ Benchmark results: #+END_SRC +** Agenda censoring + +For sharing screenshots of the agenda without revealing private data. + +#+BEGIN_SRC elisp + (defun org-agenda-sharpie () + "Censor the text of items in the agenda." + (interactive) + (let (regexp old-heading new-heading properties) + ;; Save face properties of line in agenda to reapply to changed text + (setq properties (text-properties-at (point))) + + ;; Go to source buffer + (org-with-point-at (org-find-text-property-in-string 'org-marker + (buffer-substring (line-beginning-position) + (line-end-position))) + ;; Save old heading text and ask for new text + (line-beginning-position) + (unless (org-at-heading-p) + ;; Not sure if necessary + (org-back-to-heading)) + (setq old-heading (when (looking-at org-complex-heading-regexp) + (match-string 4)))) + (setq new-heading (read-from-minibuffer "Overwrite visible heading with: ")) + (add-text-properties 0 (length new-heading) properties new-heading) + ;; Back to agenda buffer + (save-excursion + (when (and old-heading new-heading) + ;; Replace agenda text + (let ((inhibit-read-only t)) + (goto-char (line-beginning-position)) + (when (search-forward old-heading (line-end-position)) + (replace-match new-heading 'fixedcase 'literal))))))) +#+END_SRC + ** Agenda examining This helps a lot. @@ -3128,39 +3189,12 @@ This helps a lot. 0 5))) #+END_SRC -** Agenda censoring - -For sharing screenshots of the agenda without revealing private data. +** Auto categories #+BEGIN_SRC elisp - (defun org-agenda-sharpie () - "Censor the text of items in the agenda." - (interactive) - (let (regexp old-heading new-heading properties) - ;; Save face properties of line in agenda to reapply to changed text - (setq properties (text-properties-at (point))) - - ;; Go to source buffer - (org-with-point-at (org-find-text-property-in-string 'org-marker - (buffer-substring (line-beginning-position) - (line-end-position))) - ;; Save old heading text and ask for new text - (line-beginning-position) - (unless (org-at-heading-p) - ;; Not sure if necessary - (org-back-to-heading)) - (setq old-heading (when (looking-at org-complex-heading-regexp) - (match-string 4)))) - (setq new-heading (read-from-minibuffer "Overwrite visible heading with: ")) - (add-text-properties 0 (length new-heading) properties new-heading) - ;; Back to agenda buffer - (save-excursion - (when (and old-heading new-heading) - ;; Replace agenda text - (let ((inhibit-read-only t)) - (goto-char (line-beginning-position)) - (when (search-forward old-heading (line-end-position)) - (replace-match new-heading 'fixedcase 'literal))))))) + (let ((org-super-agenda-groups + '((:auto-category t)))) + (org-agenda-list nil nil 'day)) #+END_SRC ** Auto grouping @@ -3174,14 +3208,6 @@ For sharing screenshots of the agenda without revealing private data. (org-agenda-list nil nil 'day))) #+END_SRC -** Auto categories - -#+BEGIN_SRC elisp - (let ((org-super-agenda-groups - '((:auto-category t)))) - (org-agenda-list nil nil 'day)) -#+END_SRC - ** Date #+BEGIN_SRC elisp @@ -3278,3 +3304,11 @@ I don't need this right now, but it might come in handy here or elsewhere. #+END_SRC +* [#C] COMMENT Config :noexport: + +** File-local variables + +# Local Variables: +# before-save-hook: (org-make-toc (lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o)))))) +# End: + From b10522de6fc48306bdf1df1130d340db9e5c731f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Nov 2020 22:15:54 -0600 Subject: [PATCH 145/560] Notes: Add idea --- notes.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/notes.org b/notes.org index 5a9306b..5452820 100644 --- a/notes.org +++ b/notes.org @@ -20,6 +20,7 @@ :END: :CONTENTS: - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] +- [[#consider-using-parsec-for-parsing-queries][Consider using parsec for parsing queries]] - [[#document-sorters][Document sorters]] - [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] @@ -611,6 +612,10 @@ Appears to be another implementation of magit-section-like expandable sections. **** magit-section +** MAYBE Consider using [[https://github.com/cute-jumper/parsec.el][parsec]] for parsing queries + +=peg= is a bit older and perhaps unmaintained now. + ** MAYBE Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. From a91bb208a347441e5332a537e5b56840bd9e47e3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 8 Nov 2020 23:29:41 -0600 Subject: [PATCH 146/560] Notes: Update --- notes.org | 87 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/notes.org b/notes.org index 5452820..12ec0a7 100644 --- a/notes.org +++ b/notes.org @@ -20,11 +20,9 @@ :END: :CONTENTS: - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] -- [[#consider-using-parsec-for-parsing-queries][Consider using parsec for parsing queries]] - [[#document-sorters][Document sorters]] - [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] -- [[#tools-for-saving-queries-and-accessing-them-24][Tools for saving queries and accessing them {2/4}]] - [[#add-more-sorters][Add more sorters?]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#default-sort][Default sort]] @@ -39,9 +37,11 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] +- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#outline-path-predicate][Outline path predicate]] - [[#node-caching]["Node" caching]] - [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] +- [[#consider-using-parsec-for-parsing-queries][Consider using parsec for parsing queries]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#use-bovine-or-wisent-to-parse-non-sexp-syntax][Use Bovine or Wisent to parse non-sexp syntax]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] @@ -79,27 +79,6 @@ e.g. Also, should support an ~id~ one. -** TODO [#A] Tools for saving queries and accessing them [2/4] - -+ Added example to =examples.org=. - -*** TODO Bookmarks - -*** TODO Org link types -:PROPERTIES: -:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e -:END: - -This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. - -**** TODO For all parameters - -**** TODO For saved queries - -*** DONE Access saved query from saved query list - -*** DONE Save query from ql-agenda buffer - ** TODO [#B] Add more sorters? + [ ] =category= @@ -430,6 +409,68 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary +** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + ++ Added example to =examples.org=. + +*** UNDERWAY [#A] Org link types +:PROPERTIES: +:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e +:END: + +This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. + +[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: + +#+BEGIN_SRC org + [[org-ql-search:property:author="AUTHOR"]] +#+END_SRC + +[2020-11-08 Sun 23:22] Seems to work! + +#+BEGIN_SRC elisp + ;;;; Org link type + + ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. + + (org-link-set-parameters "org-ql-search" + :follow #'org-ql-search--link-open + :store #'org-ql-search--link-store) + + (defun org-ql-search--link-open (query) + "Open Org QL QUERY for current buffer." + (org-ql-search (current-buffer) query)) + + (defun org-ql-search--link-store () + "Store a link to current Org QL query." + ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. + (when org-ql-view-query + (org-store-link-props :type "org-ql-search" + :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) + :description org-ql-view-title) + t)) +#+END_SRC + +Tested on these queries: + +#+BEGIN_SRC org + + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] + + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] + + [[org-ql-search:link:nullprogram]] +#+END_SRC + +**** TODO For all parameters + +**** TODO For saved queries + +*** DONE Bookmarks + +[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. + +*** DONE Access saved query from saved query list + +*** DONE Save query from ql-agenda buffer + ** UNDERWAY [#A] Outline path predicate [2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: From 9f98b87a8efb4831c2093ff613cb02f37528191a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 00:20:33 -0600 Subject: [PATCH 147/560] Comment: Add FIXME --- org-ql-search.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-search.el b/org-ql-search.el index f84dfed..1609d9e 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -92,6 +92,7 @@ Runs `org-occur-hook' after making the sparse tree." (org-remove-occur-highlights nil nil t) (org-overview)) (let ((num-results 0)) + ;; FIXME: Accept plain queries as well. (org-ql-select buffer query :action (lambda () (org-show-context 'occur-tree) From 17fd923fc98d20931c464e1ce3f1244657982599 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 01:32:04 -0600 Subject: [PATCH 148/560] Meta: Delete Cask file --- Cask | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 Cask diff --git a/Cask b/Cask deleted file mode 100644 index 7afe920..0000000 --- a/Cask +++ /dev/null @@ -1,10 +0,0 @@ -(package-file "org-ql.el") - -(files "org-ql.el" "org-ql-agenda.el") - -(source gnu) -(source melpa) - -(development - (depends-on "buttercup") - (depends-on "xr")) From 73e17844a3ffe7d3c73fe480a0dc286d8a584c7a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 01:41:05 -0600 Subject: [PATCH 149/560] Meta: Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ad6347b..fa4f2fc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /sandbox/ /.sandbox/ /scratch.org +/scratch/ +/worktrees/ From 90b7a9a48b7b26f8eb03a556880d11bf00732b6a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 01:55:47 -0600 Subject: [PATCH 150/560] Notes: Update --- notes.org | 354 +++++++++++++++++++++++++++--------------------------- 1 file changed, 177 insertions(+), 177 deletions(-) diff --git a/notes.org b/notes.org index 12ec0a7..afa25fb 100644 --- a/notes.org +++ b/notes.org @@ -27,7 +27,7 @@ - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#default-sort][Default sort]] - [[#dynamic-blocks][Dynamic blocks]] -- [[#fancier-plain-query-syntax-for-tags-and-properties][Fancier plain query syntax for tags and properties]] +- [[#partial-match-for-property-queries][Partial match for property queries]] - [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] - [[#normalize-queries][Normalize queries]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] @@ -41,9 +41,8 @@ - [[#outline-path-predicate][Outline path predicate]] - [[#node-caching]["Node" caching]] - [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] -- [[#consider-using-parsec-for-parsing-queries][Consider using parsec for parsing queries]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] -- [[#use-bovine-or-wisent-to-parse-non-sexp-syntax][Use Bovine or Wisent to parse non-sexp syntax]] +- [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] - [[#helm-command][Helm command]] - [[#byte-compile-lambdas][Byte-compile lambdas]] @@ -65,7 +64,11 @@ Note that the built-in sorting only works on Org elements, which is the default [2020-01-16 Thu 06:20] This idea just came to me when I was thinking about using the search-based paradigm vs. outline-based. This would allow both, e.g. some kind of =#+BEGIN_QUERY= block that would update when =C-c C-c= is pressed on it. -** TODO [#A] Outline path in buffers-files arg +** TODO [#A] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ + +For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. + +** TODO [#B] Outline path in buffers-files arg :PROPERTIES: :ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 :END: @@ -84,19 +87,11 @@ Also, should support an ~id~ one. + [ ] =category= + [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry -** TODO [#B] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ - -For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. - ** TODO [#B] Default sort Would probably be useful to have a default sort option. -** TODO Dynamic blocks - -For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. - -** TODO [#B] Fancier plain query syntax for tags and properties +** TODO [#B] Partial match for property queries e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. @@ -112,11 +107,15 @@ e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. -** TODO [#B] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] +** TODO [#C] Dynamic blocks + +For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. + +** TODO [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] [2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. -** TODO [#B] Normalize queries +** TODO [#C] Normalize queries [2019-07-16 Tue 11:49] This serves two purposes: @@ -125,11 +124,157 @@ Searching that with a query like =property:author=Fabrice= returns nothing; the So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. -** TODO [#B] Quickly change sorting/grouping in search views +** TODO [#C] Update view screenshots -With caching, the search doesn't need to be repeated, so resorting/regrouping can be very fast. +e.g. doesn't currently show the =View= header. -** TODO [#B] Recursive queries +** TODO [#C] ~org-agenda-skip-function~ + +As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: + +#+BEGIN_SRC elisp + ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- + + (defun org-ql-skip-function (query) + "Return a function for `org-agenda-skip-function' for QUERY. + Compared to using QUERY in `org-ql', this effectively turns QUERY + into (not QUERY)." + (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) + (lambda () + ;; This duplicates the functionality of `org-ql--select'. + (let (orig-fns) + (--each org-ql-predicates + ;; Save original function mappings. + (let ((name (plist-get it :name))) + (push (list :name name :fn (symbol-function name)) orig-fns))) + (unwind-protect + (progn + (--each org-ql-predicates + ;; Set predicate functions. + (fset (plist-get it :name) (plist-get it :fn))) + ;; Run query. + ;; FIXME: "If this function returns nil, the current match should not be skipped. + ;; Otherwise, the function must return a position from where the search + ;; should be continued." + (funcall predicate)) + (--each orig-fns + ;; Restore original function mappings. + (fset (plist-get it :name) (plist-get it :fn)))))))) + + (let ((org-agenda-custom-commands + '(("z" "Z" + ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) + ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) + ((org-agenda-files ("~/org/inbox.org")))))) + (org-agenda nil "z")) +#+END_SRC + +I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... + +** TODO [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + +** TODO [#C] Update commentary + +** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + ++ Added example to =examples.org=. + +*** UNDERWAY [#A] Org link types +:PROPERTIES: +:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e +:END: + +This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. + +[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: + +#+BEGIN_SRC org + [[org-ql-search:property:author="AUTHOR"]] +#+END_SRC + +[2020-11-08 Sun 23:22] Seems to work! + +#+BEGIN_SRC elisp + ;;;; Org link type + + ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. + + (org-link-set-parameters "org-ql-search" + :follow #'org-ql-search--link-open + :store #'org-ql-search--link-store) + + (defun org-ql-search--link-open (query) + "Open Org QL QUERY for current buffer." + (org-ql-search (current-buffer) query)) + + (defun org-ql-search--link-store () + "Store a link to current Org QL query." + ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. + (when org-ql-view-query + (org-store-link-props :type "org-ql-search" + :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) + :description org-ql-view-title) + t)) +#+END_SRC + +Tested on these queries: + +#+BEGIN_SRC org + + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] + + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] + + [[org-ql-search:link:nullprogram]] +#+END_SRC + +**** TODO For all parameters + +**** TODO For saved queries + +*** DONE Bookmarks + +[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. + +*** DONE Access saved query from saved query list + +*** DONE Save query from ql-agenda buffer + +** UNDERWAY [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. + +** UNDERWAY [#B] Recursive queries For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. @@ -205,7 +350,7 @@ This works pretty well. It needs polishing, and some refactoring so items can b -non-nil)))) #+END_SRC -** TODO [#B] Timeline view +** UNDERWAY [#B] Timeline view :PROPERTIES: :ID: 00573552-ffe9-4608-8904-7f6c73246b6d :END: @@ -356,156 +501,6 @@ Another, more up-to-date implementation: [2019-09-26 Thu 21:28] Would probably make sense to implement this using the view-sections someday. -** TODO [#B] Update view screenshots - -e.g. doesn't currently show the =View= header. - -** TODO [#C] ~org-agenda-skip-function~ - -As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: - -#+BEGIN_SRC elisp - ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- - - (defun org-ql-skip-function (query) - "Return a function for `org-agenda-skip-function' for QUERY. - Compared to using QUERY in `org-ql', this effectively turns QUERY - into (not QUERY)." - (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) - (lambda () - ;; This duplicates the functionality of `org-ql--select'. - (let (orig-fns) - (--each org-ql-predicates - ;; Save original function mappings. - (let ((name (plist-get it :name))) - (push (list :name name :fn (symbol-function name)) orig-fns))) - (unwind-protect - (progn - (--each org-ql-predicates - ;; Set predicate functions. - (fset (plist-get it :name) (plist-get it :fn))) - ;; Run query. - ;; FIXME: "If this function returns nil, the current match should not be skipped. - ;; Otherwise, the function must return a position from where the search - ;; should be continued." - (funcall predicate)) - (--each orig-fns - ;; Restore original function mappings. - (fset (plist-get it :name) (plist-get it :fn)))))))) - - (let ((org-agenda-custom-commands - '(("z" "Z" - ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) - ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) - ((org-agenda-files ("~/org/inbox.org")))))) - (org-agenda nil "z")) -#+END_SRC - -I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... - -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** TODO [#C] Update commentary - -** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] - -+ Added example to =examples.org=. - -*** UNDERWAY [#A] Org link types -:PROPERTIES: -:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e -:END: - -This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. - -[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: - -#+BEGIN_SRC org - [[org-ql-search:property:author="AUTHOR"]] -#+END_SRC - -[2020-11-08 Sun 23:22] Seems to work! - -#+BEGIN_SRC elisp - ;;;; Org link type - - ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. - - (org-link-set-parameters "org-ql-search" - :follow #'org-ql-search--link-open - :store #'org-ql-search--link-store) - - (defun org-ql-search--link-open (query) - "Open Org QL QUERY for current buffer." - (org-ql-search (current-buffer) query)) - - (defun org-ql-search--link-store () - "Store a link to current Org QL query." - ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. - (when org-ql-view-query - (org-store-link-props :type "org-ql-search" - :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) - :description org-ql-view-title) - t)) -#+END_SRC - -Tested on these queries: - -#+BEGIN_SRC org - + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] - + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] - + [[org-ql-search:link:nullprogram]] -#+END_SRC - -**** TODO For all parameters - -**** TODO For saved queries - -*** DONE Bookmarks - -[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. - -*** DONE Access saved query from saved query list - -*** DONE Save query from ql-agenda buffer - -** UNDERWAY [#A] Outline path predicate - -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: - -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. - ** UNDERWAY [#B] "Node" caching [2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. @@ -620,7 +615,7 @@ One of the things in that branch is =org-ql-item=, which is a struct used to car Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. -*** TODO Experiment with =widget= +*** MAYBE [#C] Experiment with =widget= The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. @@ -653,17 +648,18 @@ Appears to be another implementation of magit-section-like expandable sections. **** magit-section -** MAYBE Consider using [[https://github.com/cute-jumper/parsec.el][parsec]] for parsing queries - -=peg= is a bit older and perhaps unmaintained now. - -** MAYBE Overlay-based caching inspired by org-num-mode +** MAYBE [#C] Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. -** MAYBE Use Bovine or Wisent to parse non-sexp syntax +[2020-11-09 Mon 01:51] I feel like that's probably unlikely to work well. I imagine it would require storing the query at every heading, which would be very wasteful. As well, adding more overlays to an Org buffer is probably not a good idea, because there are already enough of those. -They're both built-in to Emacs, so we could drop the =peg= dependency. +However, there might still be a useful idea here somewhere... + +** MAYBE [#C] Alternative parsing libraries + ++ e.g. Bovine and Wisent come with Emacs, which would allow us to drop the =peg= dependency (which doesn't use lexical binding). ++ [[https://github.com/cute-jumper/parsec.el][parsec]] is third-party, but looks powerful ** MAYBE [#C] Fancier searching for inherited tags @@ -788,6 +784,10 @@ Well, a bit of fiddling (lots of trial-and-error required) produced this: That seems pretty usable! +** DONE [#B] Quickly change sorting/grouping in search views + +With caching, the search doesn't need to be repeated, so resorting/regrouping can be very fast. + ** DONE Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] :LOGBOOK: From 2c466ebdcd6718a8df28a16b02967ac70f4e89d2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 22:42:59 -0600 Subject: [PATCH 151/560] Notes: Dynamic blocks update --- notes.org | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 352 insertions(+), 9 deletions(-) diff --git a/notes.org b/notes.org index afa25fb..8082013 100644 --- a/notes.org +++ b/notes.org @@ -5,6 +5,7 @@ :TOC: :include siblings :depth 1 :ignore this :force depth :END: :CONTENTS: +- [[#overview][Overview]] - [[#tasks][Tasks]] - [[#examples--testing][Examples / testing]] - [[#in-the-wild][In the wild]] @@ -13,6 +14,22 @@ - [[#testing][Testing]] :END: +* [#A] Overview + +#+BEGIN: org-ql :query (todo "UNDERWAY") :format (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +| Priority | Todo | Heading | +|----------+----------+--------------------------------------------------------------------| +| A | UNDERWAY | [[Dynamic blocks][Dynamic blocks]] | +| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | +| A | UNDERWAY | [[Org link types][Org link types]] | +| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | +| B | UNDERWAY | [[Recursive queries][Recursive queries]] | +| B | UNDERWAY | [[Timeline view][Timeline view]] | +| B | UNDERWAY | [["Node" caching]["Node" caching]] | +| B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | +| | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | + +#+END: * [#A] Tasks :PROPERTIES: @@ -22,29 +39,30 @@ - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] - [[#document-sorters][Document sorters]] - [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] +- [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] - [[#add-more-sorters][Add more sorters?]] -- [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#default-sort][Default sort]] -- [[#dynamic-blocks][Dynamic blocks]] - [[#partial-match-for-property-queries][Partial match for property queries]] - [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] - [[#normalize-queries][Normalize queries]] -- [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] -- [[#recursive-queries][Recursive queries]] -- [[#timeline-view][Timeline view]] - [[#update-view-screenshots][Update view screenshots]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] +- [[#dynamic-blocks][Dynamic blocks]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#outline-path-predicate][Outline path predicate]] +- [[#recursive-queries][Recursive queries]] +- [[#timeline-view][Timeline view]] - [[#node-caching]["Node" caching]] - [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#group-tag-support][Group tag support]] - [[#helm-command][Helm command]] +- [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] - [[#byte-compile-lambdas][Byte-compile lambdas]] - [[#documentfigure-out-tag-inheritance][Document/figure out tag inheritance]] - [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] @@ -107,10 +125,6 @@ e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. -** TODO [#C] Dynamic blocks - -For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. - ** TODO [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] [2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. @@ -177,6 +191,83 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary +** UNDERWAY [#A] Dynamic blocks + ++ *Tasks* + - [ ] Merge code + - [ ] Document the feature + +For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. + +[2020-11-09 Mon 22:00] I just realized that this is probably much easier than I realized. + ++ [[info:org#Dynamic%20blocks][info:org#Dynamic blocks]] + +#+BEGIN_SRC elisp + (cl-defun org-dblock-write:org-ql (params) + "FIXME: Docstring" + (pcase-let* (((map :query :format :sort :ts-format) params) + (format-fns (list (cons 'heading (lambda (element) + (org-make-link-string (org-element-property :raw-value element) + (org-element-property :raw-value element)))) + (cons 'todo (lambda (element) + (or (org-element-property :todo-keyword element) + ""))) + (cons 'priority (lambda (element) + (--if-let (org-element-property :priority element) + (char-to-string it) + ""))) + (cons 'deadline (lambda (element) + (--if-let (org-element-property :deadline element) + (ts-format ts-format (ts-parse-org-element it )) + ""))) + (cons 'scheduled (lambda (element) + (--if-let (org-element-property :scheduled element) + (ts-format ts-format (ts-parse-org-element it )) + ""))))) + (elements (org-ql-query :from (current-buffer) + :where query + :select '(org-element-headline-parser (line-end-position)) + :order-by sort))) + (cl-labels ((format-element + (element) (string-join (cl-loop for prop in format + for fn = (alist-get prop format-fns) + collect (funcall fn element)) + " | "))) + (insert "| " (string-join (--map (capitalize (symbol-name it)) format) " | ") " |" "\n") + (insert "|- \n") + (dolist (element elements) + (insert "| " (format-element element) " |" "\n")) + (org-table-align)))) +#+END_SRC + +[2020-11-09 Mon 22:35] This works pretty well! For example: + +#+BEGIN_SRC org + ,#+BEGIN: org-ql :query (todo) :format (priority todo heading deadline scheduled) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" + | Priority | Todo | Heading | Deadline | Scheduled | + |----------+-------+------------+------------------+------------------| + | A | TODAY | Heading 1 | 2020-11-11 00:00 | | + | B | TODO | Heading 2 | | 2020-11-09 00:00 | + + ,#+END: + + ,#+BEGIN: columnview :id global :hlines t :indent t + | ITEM | TODO | PRIORITY | TAGS | + |----------------+-------+----------+------| + | Test heading 1 | TODAY | B | | + |----------------+-------+----------+------| + | Heading 2 | TODO | B | | + ,#+END: + + ,* TODAY [#A] Heading 1 + DEADLINE: <2020-11-11 Wed> + + ,* TODO [#B] Heading 2 + SCHEDULED: <2020-11-09 Mon> + +#+END_SRC + ** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + Added example to =examples.org=. @@ -665,6 +756,258 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** PROJECT [#A] Group tag support + +*** UNDERWAY Benchmarking tags searches without and with new group-tags support + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 10 :ensure-equal t + :forms (("without group-tags support" + (org-ql-select (org-ql-search-directories-files) + '(tags "Emacs") + :action #'point)) + )) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------------------------+--------------------+---------------+----------+------------------| +| without group-tags support | slowest | 5.512271 | 0 | 0 | + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 10 :ensure-equal t + :forms (("with group-tags support" + (org-ql-select (org-ql-search-directories-files) + '(tags "Emacs") + :action #'point)) + )) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|-------------------------+--------------------+---------------+----------+------------------| +| with group-tags support | slowest | 5.154639 | 0 | 0 | + +[2020-11-09 Mon 17:43] I think I need to enhance the benchmarking macros to make this easier. But that might require copying much of =benchmark-run-compiled=, so let me try something else: This is messy, but it ought to be fair enough (the only difference being the minor change in =org-ql--tags-at=. + +#+BEGIN_SRC elisp + (bench-multi-lexical :times 10 :ensure-equal t + :forms (("without group-tags support" + (progn + (setf org-ql-cache (make-hash-table :weakness 'key) + org-ql-tags-cache (make-hash-table :weakness 'key) + org-ql-node-value-cache (make-hash-table :weakness 'key)) + (defun org-ql--expand-tag-hierarchy (tags &optional excluded) + "Return TAGS along with their associated group tags. + This function recursively searches for groups that each given tag belongs to, + directly or indirectly, and includes the corresponding group tags to the result. + + TAGS should be a list of tags (i.e., strings). + If non-nil, EXCLUDED should be a list of group tags that will not be + automatically added to the results unless they are already in TAGS." + (let ((groups (org-tag-alist-to-groups org-current-tag-alist)) + (excluded (append tags excluded))) + (let (group-tags) + (dolist (tag tags) + (pcase-dolist (`(,group-tag . ,group-members) groups) + (when (and (not (member group-tag excluded)) + ;; Check if one of the members in the group matches tag. + ;; Notice that each member may be a plain string or + ;; a regexp pattern (enclosed between curly brackets). + (--some (if (string-match-p "^[{].+[}]$" it) + ;; If pattern (it) is a regexp, remove the brackets and + ;; make sure that it either matches the whole tag or not. + (string-match-p (concat "^" (substring it 1 -1) "$") tag) + ;; Check if member (it) is identical to tag. + (string= it tag)) + group-members)) + (push group-tag group-tags)))) + ;; If group tags not already included have been found, + ;; then recursively expand them as well. + ;; Notice that by passing (group-tags excluded) to the next call + ;; instead of ((append tags group-tags)) ensures that we do not + ;; unnecessarily loop over the elements of TAGS more than once. + (if group-tags + (append tags (org-ql--expand-tag-hierarchy group-tags excluded)) + tags)))) + (defun org-ql--tags-at (position) + "Return tags for POSITION in current buffer. + Returns cons (INHERITED-TAGS . LOCAL-TAGS)." + ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables + ;; bound in the else clause, so destructured variables that are non-nil, + ;; like found caches, are not available in the else clause. + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) + (modified-tick (car buffer-cache)) + (tags-cache (cdr buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cached-result (gethash position tags-cache))) + ;; Found in cache: return them. + (pcase cached-result + ('org-ql-nil nil) + (_ cached-result)) + ;; Not found in cache: get tags and cache them. + (let* ((local-tags (or (when (looking-at org-ql-tag-line-re) + (split-string (match-string-no-properties 2) ":" t)) + 'org-ql-nil)) + (inherited-tags (or (when org-use-tag-inheritance + (save-excursion + (if (org-up-heading-safe) + ;; Return parent heading's tags. + (-let* (((inherited local) (org-ql--tags-at (point))) + (tags (when (or inherited local) + (cond ((and (listp inherited) + (listp local)) + (->> (append inherited local) + -non-nil -uniq)) + ((listp inherited) inherited) + ((listp local) local))))) + (cl-typecase org-use-tag-inheritance + (list (setf tags (-intersection tags org-use-tag-inheritance))) + (string (setf tags (--select (string-match org-use-tag-inheritance it) + tags)))) + (pcase org-tags-exclude-from-inheritance + ('nil tags) + (_ (-difference tags org-tags-exclude-from-inheritance)))) + ;; Top-level heading: use file tags. + org-file-tags))) + 'org-ql-nil)) + (all-tags (list inherited-tags local-tags))) + ;; Check caches again, because they may have been set now. + ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? + (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) + modified-tick (car buffer-cache) + tags-cache (cdr buffer-cache) + buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (unless (and buffer-cache buffer-unmodified-p) + ;; Buffer-local tags cache empty or invalid: make new one. + (setf tags-cache (make-hash-table)) + (puthash (current-buffer) + (cons (buffer-modified-tick) tags-cache) + org-ql-tags-cache)) + (puthash position all-tags tags-cache)))) + (org-ql-select (org-ql-search-directories-files) + '(tags "Emacs") + :action #'point))) + ("with group-tags support" + (progn + (setf org-ql-cache (make-hash-table :weakness 'key) + org-ql-tags-cache (make-hash-table :weakness 'key) + org-ql-node-value-cache (make-hash-table :weakness 'key)) + (defun org-ql--expand-tag-hierarchy (tags &optional excluded) + "Return TAGS along with their associated group tags. + This function recursively searches for groups that each given tag belongs to, + directly or indirectly, and includes the corresponding group tags to the result. + + TAGS should be a list of tags (i.e., strings). + If non-nil, EXCLUDED should be a list of group tags that will not be + automatically added to the results unless they are already in TAGS." + (let ((groups (org-tag-alist-to-groups org-current-tag-alist)) + (excluded (append tags excluded))) + (let (group-tags) + (dolist (tag tags) + (pcase-dolist (`(,group-tag . ,group-members) groups) + (when (and (not (member group-tag excluded)) + ;; Check if one of the members in the group matches tag. + ;; Notice that each member may be a plain string or + ;; a regexp pattern (enclosed between curly brackets). + (--some (if (string-match-p "^[{].+[}]$" it) + ;; If pattern (it) is a regexp, remove the brackets and + ;; make sure that it either matches the whole tag or not. + (string-match-p (concat "^" (substring it 1 -1) "$") tag) + ;; Check if member (it) is identical to tag. + (string= it tag)) + group-members)) + (push group-tag group-tags)))) + ;; If group tags not already included have been found, + ;; then recursively expand them as well. + ;; Notice that by passing (group-tags excluded) to the next call + ;; instead of ((append tags group-tags)) ensures that we do not + ;; unnecessarily loop over the elements of TAGS more than once. + (if group-tags + (append tags (org-ql--expand-tag-hierarchy group-tags excluded)) + tags)))) + (defun org-ql--tags-at (position) + "Return tags for POSITION in current buffer. + Returns cons (INHERITED-TAGS . LOCAL-TAGS)." + ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables + ;; bound in the else clause, so destructured variables that are non-nil, + ;; like found caches, are not available in the else clause. + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) + (modified-tick (car buffer-cache)) + (tags-cache (cdr buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cached-result (gethash position tags-cache))) + ;; Found in cache: return them. + (pcase cached-result + ('org-ql-nil nil) + (_ cached-result)) + ;; Not found in cache: get tags and cache them. + (let* ((local-tags (or (when (looking-at org-ql-tag-line-re) + (split-string (match-string-no-properties 2) ":" t)) + 'org-ql-nil)) + (inherited-tags (or (when org-use-tag-inheritance + (save-excursion + (if (org-up-heading-safe) + ;; Return parent heading's tags. + (-let* (((inherited local) (org-ql--tags-at (point))) + (tags (when (or inherited local) + (cond ((and (listp inherited) + (listp local)) + (->> (append inherited local) + -non-nil -uniq)) + ((listp inherited) inherited) + ((listp local) local))))) + (cl-typecase org-use-tag-inheritance + (list (setf tags (-intersection tags org-use-tag-inheritance))) + (string (setf tags (--select (string-match org-use-tag-inheritance it) + tags)))) + (pcase org-tags-exclude-from-inheritance + ('nil tags) + (_ (-difference tags org-tags-exclude-from-inheritance)))) + ;; Top-level heading: use file tags. + org-file-tags))) + 'org-ql-nil)) + all-tags) + (when org-group-tags + (unless (eq local-tags 'org-ql-nil) + (setq local-tags (org-ql--expand-tag-hierarchy local-tags))) + (unless (eq inherited-tags 'org-ql-nil) + (setq inherited-tags (org-ql--expand-tag-hierarchy inherited-tags)))) + (setq all-tags (list inherited-tags local-tags)) + ;; Check caches again, because they may have been set now. + ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? + (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) + modified-tick (car buffer-cache) + tags-cache (cdr buffer-cache) + buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (unless (and buffer-cache buffer-unmodified-p) + ;; Buffer-local tags cache empty or invalid: make new one. + (setf tags-cache (make-hash-table)) + (puthash (current-buffer) + (cons (buffer-modified-tick) tags-cache) + org-ql-tags-cache)) + (puthash position all-tags tags-cache)))) + (org-ql-select (org-ql-search-directories-files) + '(tags "Emacs") + :action #'point))) + )) +#+END_SRC + +#+RESULTS: +| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | +|----------------------------+--------------------+---------------+----------+------------------| +| without group-tags support | 1.01 | 52.832562 | 4 | 1.989522 | +| with group-tags support | slowest | 53.425342 | 5 | 2.479128 | + +[2020-11-09 Mon 17:57] Well, the performance difference seems smaller than I expected. For single iterations, it ought to be unnoticeable. Although I'm still a bit skeptical about this benchmark: I feel like it ought to have more of an impact than that, but maybe I'm wrong--and that would be great! + +Next steps: + ++ [X] Post benchmark code on PR and ask Panagiotis to verify ++ [X] Also ask him to run benchmark actually using group tags (since I don't actually have any, even though the boolean is t) ++ [X] Discuss caching of group tag expansion. It seems like we ought to cache the expansions as well, because sibling headings (especially at level 1) ought to get their group tags re-expanded individually, even when we've already expanded them for another heading. ++ [X] Remove unused =result= variable + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. From c0ded3ded3a81b2597c761f787085750f42e842c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 9 Nov 2020 23:50:34 -0600 Subject: [PATCH 152/560] Add: Dynamic block --- README.org | 32 +++++++++++ notes.org | 10 ++-- org-ql-search.el | 75 ++++++++++++++++++++++++++ org-ql.info | 136 +++++++++++++++++++++++++++++++---------------- 4 files changed, 202 insertions(+), 51 deletions(-) diff --git a/README.org b/README.org index 605b7bc..2a52476 100644 --- a/README.org +++ b/README.org @@ -68,6 +68,7 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: - [[#ancestordescendant-predicates][Ancestor/descendant predicates]] - [[#datetime-predicates][Date/time predicates]] - [[#functions--macros][Functions / Macros]] +- [[#dynamic-block][Dynamic block]] - [[#tips][Tips]] :END: @@ -396,6 +397,36 @@ Examples: Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted. +** Dynamic block + +Org QL provides a dynamic block that lists entries in the current document matching a query. In the header, these parameters are supported: + ++ ~:query~: An Org QL query expression in either sexp or non-sexp form. ++ ~:columns~ A list of columns, including ~heading~, ~todo~, ~priority~, ~deadline~, ~scheduled~. ++ ~:sort~ One or a list of Org QL sorting methods (see ~org-ql-select~). ++ ~:take~ Optionally take a number of results from the front (a positive number) or the end (a negative number) of the results. ++ ~:ts-format~ Optional format string used to format timestamp-based columns. + +The heading column is formatted as a link to the heading (not shown in the following example). + +For example, this dynamic block shows the first seven headings that are to-do items with priority A or B, sorted by deadline then priority, with certain columns and timestamp format: + +# NOTE: These results are edited manually because the Org links don't display well in the Info manual. + +#+BEGIN_SRC org + ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | Priority | Deadline | Heading | + |------+----------+------------------+---------------------------------------| + | TODO | A | 2017-07-07 00:00 | Take over the world | + | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | 2017-07-15 00:00 | Take over the universe | + | TODO | B | 2017-07-21 00:00 | Internet | + | TODO | A | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | Skype with president of Antarctica | + | TODO | B | | Take over Mars | + ,#+END: +#+END_SRC + ** Tips + Org QL View buffers can be bookmarked with Emacs bookmark commands, e.g. =C-x r m=. This also integrates with [[https://github.com/alphapapa/org-sidebar][org-sidebar]] and [[https://github.com/alphapapa/burly.el][Burly]]. @@ -413,6 +444,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. + Predicate =link=, which matches descriptions and targets in Org links. + Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) ++ Dynamic block support. + Mascot. *Changed* diff --git a/notes.org b/notes.org index 8082013..a66e80c 100644 --- a/notes.org +++ b/notes.org @@ -16,7 +16,7 @@ * [#A] Overview -#+BEGIN: org-ql :query (todo "UNDERWAY") :format (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +#+BEGIN: org-ql :query (todo "UNDERWAY") :columns (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" | Priority | Todo | Heading | |----------+----------+--------------------------------------------------------------------| | A | UNDERWAY | [[Dynamic blocks][Dynamic blocks]] | @@ -206,7 +206,7 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this #+BEGIN_SRC elisp (cl-defun org-dblock-write:org-ql (params) "FIXME: Docstring" - (pcase-let* (((map :query :format :sort :ts-format) params) + (pcase-let* (((map :query :columns :sort :ts-format) params) (format-fns (list (cons 'heading (lambda (element) (org-make-link-string (org-element-property :raw-value element) (org-element-property :raw-value element)))) @@ -230,11 +230,11 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this :select '(org-element-headline-parser (line-end-position)) :order-by sort))) (cl-labels ((format-element - (element) (string-join (cl-loop for prop in format - for fn = (alist-get prop format-fns) + (element) (string-join (cl-loop for column in columns + for fn = (alist-get column format-fns) collect (funcall fn element)) " | "))) - (insert "| " (string-join (--map (capitalize (symbol-name it)) format) " | ") " |" "\n") + (insert "| " (string-join (--map (capitalize (symbol-name it)) columns) " | ") " |" "\n") (insert "|- \n") (dolist (element elements) (insert "| " (format-element element) " |" "\n")) diff --git a/org-ql-search.el b/org-ql-search.el index 1609d9e..c82d6f0 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -232,6 +232,81 @@ automatically from the query." ;;;###autoload (defalias 'org-ql-block 'org-ql-search-block) +;;;; Dynamic blocks + +;; This section implements support for Org dynamic blocks. See Info node `(org)Dynamic blocks'. + +(require 'org-table) + +(cl-defun org-dblock-write:org-ql (params) + "Insert content for org-ql dynamic block at point according to PARAMS. +Valid parameters include: + + :query An Org QL query expression in either sexp or non-sexp form. + + :columns A list of columns, including `heading', `todo', + `priority', `deadline', `scheduled'. + + :sort One or a list of Org QL sorting methods (see `org-ql-select'). + + :take Optionally take a number of results from the front (a + positive number) or the end (a negative number) of the results. + + :ts-format Optional format string used to format timestamp-based columns. + +For example, an org-ql dynamic block header could look like: + + #+BEGIN: org-ql :query (todo \"UNDERWAY\") :columns (priority todo heading) :sort (priority date) :ts-format \"%Y-%m-%d %H:%M\"" + (pcase-let* (((map :query :columns :sort :ts-format :take) params) + (query (cl-etypecase query + (string (org-ql--plain-query query)) + (t query))) + (columns (or columns '(heading todo priority))) + ;; MAYBE: Custom column functions. + (format-fns + ;; NOTE: Backquoting this alist prevents the lambdas from seeing + ;; the variable `ts-format', so we use `list' and `cons'. + (list (cons 'heading (lambda (element) + (org-make-link-string (org-element-property :raw-value element) + (org-element-property :raw-value element)))) + (cons 'todo (lambda (element) + (org-element-property :todo-keyword element))) + (cons 'priority (lambda (element) + (--when-let (org-element-property :priority element) + (char-to-string it)))) + (cons 'deadline (lambda (element) + (--when-let (org-element-property :deadline element) + (ts-format ts-format (ts-parse-org-element it))))) + (cons 'scheduled (lambda (element) + (--when-let (org-element-property :scheduled element) + (ts-format ts-format (ts-parse-org-element it))))))) + (elements (org-ql-query :from (current-buffer) + :where query + :select '(org-element-headline-parser (line-end-position)) + :order-by sort))) + (when take + (setf elements (cl-etypecase take + ((and integer (satisfies minusp)) (-take-last (abs take) elements)) + (integer (-take take elements))))) + (cl-labels ((format-element + (element) (string-join (cl-loop for column in columns + for fn = (alist-get column format-fns) + collect (or (funcall fn element) "")) + " | "))) + ;; Insert table header. + (insert "| " (string-join (--map (capitalize (symbol-name it)) + columns) + " | ") + " |" "\n") + ;; Separator line. + (insert "|- \n") + ;; Elements. + (dolist (element elements) + (insert "| " (format-element element) " |" "\n")) + ;; Delete final newline and align table. + (delete-char -1) + (org-table-align)))) + ;;;; Functions (cl-defun org-ql-search-directories-files (&key (directories (list org-directory)) diff --git a/org-ql.info b/org-ql.info index fea110e..afe4e3a 100644 --- a/org-ql.info +++ b/org-ql.info @@ -35,6 +35,7 @@ Usage * Commands:: * Queries:: * Functions / Macros:: +* Dynamic block:: * Tips:: Commands @@ -154,7 +155,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top ******* • • - • • • • • • + • • • • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -165,6 +166,7 @@ and polished, they will be considered stable. * Commands:: * Queries:: * Functions / Macros:: +* Dynamic block:: * Tips::  @@ -544,7 +546,7 @@ number of days. The number can be negative to invert the direction. scheduled at any time.  -File: README.info, Node: Functions / Macros, Next: Tips, Prev: Queries, Up: Usage +File: README.info, Node: Functions / Macros, Next: Dynamic block, Prev: Queries, Up: Usage 4.3 Functions / Macros ====================== @@ -711,9 +713,49 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, For convenience, arguments should be unquoted.  -File: README.info, Node: Tips, Prev: Functions / Macros, Up: Usage +File: README.info, Node: Dynamic block, Next: Tips, Prev: Functions / Macros, Up: Usage -4.4 Tips +4.4 Dynamic block +================= + +Org QL provides a dynamic block that lists entries in the current +document matching a query. In the header, these parameters are +supported: + + • ‘:query’: An Org QL query expression in either sexp or non-sexp + form. + • ‘:columns’ A list of columns, including ‘heading’, ‘todo’, + ‘priority’, ‘deadline’, ‘scheduled’. + • ‘:sort’ One or a list of Org QL sorting methods (see + ‘org-ql-select’). + • ‘:take’ Optionally take a number of results from the front (a + positive number) or the end (a negative number) of the results. + • ‘:ts-format’ Optional format string used to format timestamp-based + columns. + + The heading column is formatted as a link to the heading (not shown +in the following example). + + For example, this dynamic block shows the first seven headings that +are to-do items with priority A or B, sorted by deadline then priority, +with certain columns and timestamp format: + + #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | Priority | Deadline | Heading | + |------+----------+------------------+---------------------------------------| + | TODO | A | 2017-07-07 00:00 | Take over the world | + | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | 2017-07-15 00:00 | Take over the universe | + | TODO | B | 2017-07-21 00:00 | Internet | + | TODO | A | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | Skype with president of Antarctica | + | TODO | B | | Take over Mars | + #+END: + + +File: README.info, Node: Tips, Prev: Dynamic block, Up: Usage + +4.5 Tips ======== • Org QL View buffers can be bookmarked with Emacs bookmark commands, @@ -767,6 +809,7 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog e.g. C-x r m and shown with, e.g. C-x r b. (This also enables view restoration with Burly (https://github.com/alphapapa/burly.el).) + • Dynamic block support. • Mascot. *Changed* @@ -1188,48 +1231,49 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1521 -Node: Screenshots1644 -Node: Installation1762 -Node: Quelpa2400 -Node: Usage2843 -Node: Commands3205 -Node: org-ql-search3678 -Node: helm-org-ql5392 -Node: org-ql-view5804 -Node: org-ql-view-sidebar6304 -Node: org-ql-view-recent-items6660 -Node: org-ql-sparse-tree7144 -Node: Queries7944 -Node: Non-sexp query syntax8852 -Node: General predicates10559 -Node: Ancestor/descendant predicates15774 -Node: Date/time predicates16902 -Node: Functions / Macros19557 -Node: Agenda-like views19803 -Node: Listing / acting-on results21208 -Node: Tips25810 -Node: Changelog26141 -Node: 05-pre26780 -Node: 04627626 -Node: 04528029 -Node: 04428388 -Node: 04328745 -Node: 04228940 -Node: 04129099 -Node: 0429338 -Node: 03233269 -Node: 03133646 -Node: 0333843 -Node: 02336818 -Node: 02237046 -Node: 02137314 -Node: 0237513 -Node: 0141548 -Node: Notes41649 -Node: Comparison with Org Agenda searches41811 -Node: org-sidebar42683 -Node: License42962 +Node: Contents1539 +Node: Screenshots1662 +Node: Installation1780 +Node: Quelpa2418 +Node: Usage2861 +Node: Commands3245 +Node: org-ql-search3718 +Node: helm-org-ql5432 +Node: org-ql-view5844 +Node: org-ql-view-sidebar6344 +Node: org-ql-view-recent-items6700 +Node: org-ql-sparse-tree7184 +Node: Queries7984 +Node: Non-sexp query syntax8892 +Node: General predicates10599 +Node: Ancestor/descendant predicates15814 +Node: Date/time predicates16942 +Node: Functions / Macros19597 +Node: Agenda-like views19852 +Node: Listing / acting-on results21257 +Node: Dynamic block25859 +Node: Tips27885 +Node: Changelog28211 +Node: 05-pre28850 +Node: 04629726 +Node: 04530129 +Node: 04430488 +Node: 04330845 +Node: 04231040 +Node: 04131199 +Node: 0431438 +Node: 03235369 +Node: 03135746 +Node: 0335943 +Node: 02338918 +Node: 02239146 +Node: 02139414 +Node: 0239613 +Node: 0143648 +Node: Notes43749 +Node: Comparison with Org Agenda searches43911 +Node: org-sidebar44783 +Node: License45062  End Tag Table From 8e6aae95a0990209458c6e759c0a59eadc6bbac0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 00:04:18 -0600 Subject: [PATCH 153/560] Notes: Update --- notes.org | 157 +++++++++++++++++++++++++++--------------------------- 1 file changed, 79 insertions(+), 78 deletions(-) diff --git a/notes.org b/notes.org index a66e80c..d9f2ae9 100644 --- a/notes.org +++ b/notes.org @@ -28,7 +28,6 @@ | B | UNDERWAY | [["Node" caching]["Node" caching]] | | B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | - #+END: * [#A] Tasks @@ -191,83 +190,6 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary -** UNDERWAY [#A] Dynamic blocks - -+ *Tasks* - - [ ] Merge code - - [ ] Document the feature - -For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. - -[2020-11-09 Mon 22:00] I just realized that this is probably much easier than I realized. - -+ [[info:org#Dynamic%20blocks][info:org#Dynamic blocks]] - -#+BEGIN_SRC elisp - (cl-defun org-dblock-write:org-ql (params) - "FIXME: Docstring" - (pcase-let* (((map :query :columns :sort :ts-format) params) - (format-fns (list (cons 'heading (lambda (element) - (org-make-link-string (org-element-property :raw-value element) - (org-element-property :raw-value element)))) - (cons 'todo (lambda (element) - (or (org-element-property :todo-keyword element) - ""))) - (cons 'priority (lambda (element) - (--if-let (org-element-property :priority element) - (char-to-string it) - ""))) - (cons 'deadline (lambda (element) - (--if-let (org-element-property :deadline element) - (ts-format ts-format (ts-parse-org-element it )) - ""))) - (cons 'scheduled (lambda (element) - (--if-let (org-element-property :scheduled element) - (ts-format ts-format (ts-parse-org-element it )) - ""))))) - (elements (org-ql-query :from (current-buffer) - :where query - :select '(org-element-headline-parser (line-end-position)) - :order-by sort))) - (cl-labels ((format-element - (element) (string-join (cl-loop for column in columns - for fn = (alist-get column format-fns) - collect (funcall fn element)) - " | "))) - (insert "| " (string-join (--map (capitalize (symbol-name it)) columns) " | ") " |" "\n") - (insert "|- \n") - (dolist (element elements) - (insert "| " (format-element element) " |" "\n")) - (org-table-align)))) -#+END_SRC - -[2020-11-09 Mon 22:35] This works pretty well! For example: - -#+BEGIN_SRC org - ,#+BEGIN: org-ql :query (todo) :format (priority todo heading deadline scheduled) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" - | Priority | Todo | Heading | Deadline | Scheduled | - |----------+-------+------------+------------------+------------------| - | A | TODAY | Heading 1 | 2020-11-11 00:00 | | - | B | TODO | Heading 2 | | 2020-11-09 00:00 | - - ,#+END: - - ,#+BEGIN: columnview :id global :hlines t :indent t - | ITEM | TODO | PRIORITY | TAGS | - |----------------+-------+----------+------| - | Test heading 1 | TODAY | B | | - |----------------+-------+----------+------| - | Heading 2 | TODO | B | | - ,#+END: - - ,* TODAY [#A] Heading 1 - DEADLINE: <2020-11-11 Wed> - - ,* TODO [#B] Heading 2 - SCHEDULED: <2020-11-09 Mon> - -#+END_SRC - ** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + Added example to =examples.org=. @@ -1008,6 +930,85 @@ Next steps: + [X] Discuss caching of group tag expansion. It seems like we ought to cache the expansions as well, because sibling headings (especially at level 1) ought to get their group tags re-expanded individually, even when we've already expanded them for another heading. + [X] Remove unused =result= variable +** DONE [#A] Dynamic blocks + ++ *Tasks* + - [X] Merge code + - [X] Document the feature + +For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. + +[2020-11-09 Mon 22:00] I just realized that this is probably much easier than I realized. + ++ [[info:org#Dynamic%20blocks][info:org#Dynamic blocks]] + +#+BEGIN_SRC elisp + (cl-defun org-dblock-write:org-ql (params) + "FIXME: Docstring" + (pcase-let* (((map :query :columns :sort :ts-format) params) + (format-fns (list (cons 'heading (lambda (element) + (org-make-link-string (org-element-property :raw-value element) + (org-element-property :raw-value element)))) + (cons 'todo (lambda (element) + (or (org-element-property :todo-keyword element) + ""))) + (cons 'priority (lambda (element) + (--if-let (org-element-property :priority element) + (char-to-string it) + ""))) + (cons 'deadline (lambda (element) + (--if-let (org-element-property :deadline element) + (ts-format ts-format (ts-parse-org-element it )) + ""))) + (cons 'scheduled (lambda (element) + (--if-let (org-element-property :scheduled element) + (ts-format ts-format (ts-parse-org-element it )) + ""))))) + (elements (org-ql-query :from (current-buffer) + :where query + :select '(org-element-headline-parser (line-end-position)) + :order-by sort))) + (cl-labels ((format-element + (element) (string-join (cl-loop for column in columns + for fn = (alist-get column format-fns) + collect (funcall fn element)) + " | "))) + (insert "| " (string-join (--map (capitalize (symbol-name it)) columns) " | ") " |" "\n") + (insert "|- \n") + (dolist (element elements) + (insert "| " (format-element element) " |" "\n")) + (org-table-align)))) +#+END_SRC + +[2020-11-09 Mon 22:35] This works pretty well! For example: + +#+BEGIN_SRC org + ,#+BEGIN: org-ql :query (todo) :format (priority todo heading deadline scheduled) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" + | Priority | Todo | Heading | Deadline | Scheduled | + |----------+-------+------------+------------------+------------------| + | A | TODAY | Heading 1 | 2020-11-11 00:00 | | + | B | TODO | Heading 2 | | 2020-11-09 00:00 | + + ,#+END: + + ,#+BEGIN: columnview :id global :hlines t :indent t + | ITEM | TODO | PRIORITY | TAGS | + |----------------+-------+----------+------| + | Test heading 1 | TODAY | B | | + |----------------+-------+----------+------| + | Heading 2 | TODO | B | | + ,#+END: + + ,* TODAY [#A] Heading 1 + DEADLINE: <2020-11-11 Wed> + + ,* TODO [#B] Heading 2 + SCHEDULED: <2020-11-09 Mon> + +#+END_SRC + +[2020-11-10 Tue 00:03] I think it's ready to merge now. + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. From c0a10ba96a1543a582f5c2dd4b2f231eff63b3c0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 00:27:35 -0600 Subject: [PATCH 154/560] Fix: (org-dblock-write:org-ql) cl-minusp --- org-ql-search.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index c82d6f0..f9506f2 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -286,7 +286,7 @@ For example, an org-ql dynamic block header could look like: :order-by sort))) (when take (setf elements (cl-etypecase take - ((and integer (satisfies minusp)) (-take-last (abs take) elements)) + ((and integer (satisfies cl-minusp)) (-take-last (abs take) elements)) (integer (-take take elements))))) (cl-labels ((format-element (element) (string-join (cl-loop for column in columns From 992f3c2675d45775811b48e359ce6796d24475a9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 01:52:04 -0600 Subject: [PATCH 155/560] Add: Link support --- README.org | 15 ++++++ notes.org | 128 ++++++++++++++++++++++++++++++++++++++++++++++--- org-ql-view.el | 62 ++++++++++++++++++++++++ org-ql.info | 120 ++++++++++++++++++++++++++++------------------ 4 files changed, 271 insertions(+), 54 deletions(-) diff --git a/README.org b/README.org index 2a52476..59bbb23 100644 --- a/README.org +++ b/README.org @@ -69,6 +69,7 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: - [[#datetime-predicates][Date/time predicates]] - [[#functions--macros][Functions / Macros]] - [[#dynamic-block][Dynamic block]] +- [[#links][Links]] - [[#tips][Tips]] :END: @@ -427,6 +428,19 @@ For example, this dynamic block shows the first seven headings that are to-do it ,#+END: #+END_SRC +** Links + +Org QL View searches may be accessed by opening ~org-ql-search:~ links in an Org file. + +In an Org QL View buffer, the command ~org-store-link~ (i.e. ~C-c l~) stores a link to the current search, and it may be inserted into an Org buffer with the command ~org-insert-link~ (~C-c C-l~). The stored link records all of the view settings, like title, sorting, and grouping. + +Simple links may also be written manually in either sexp or non-sexp form, like: + +#+BEGIN_SRC org + [[org-ql-search:todo:NEXT priority:A]] + [[org-ql-search:(and (todo "NEXT") (priority "A"))]] +#+END_SRC + ** Tips + Org QL View buffers can be bookmarked with Emacs bookmark commands, e.g. =C-x r m=. This also integrates with [[https://github.com/alphapapa/org-sidebar][org-sidebar]] and [[https://github.com/alphapapa/burly.el][Burly]]. @@ -445,6 +459,7 @@ For example, this dynamic block shows the first seven headings that are to-do it + Predicate =link=, which matches descriptions and targets in Org links. + Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) + Dynamic block support. ++ Org link support (storing and opening links to Org QL View searches in the current document). + Mascot. *Changed* diff --git a/notes.org b/notes.org index d9f2ae9..78d8c32 100644 --- a/notes.org +++ b/notes.org @@ -16,12 +16,15 @@ * [#A] Overview +** Underway + +[[org-ql-search:%2528todo%2520%2522UNDERWAY%2522%2529?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] + #+BEGIN: org-ql :query (todo "UNDERWAY") :columns (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" | Priority | Todo | Heading | |----------+----------+--------------------------------------------------------------------| -| A | UNDERWAY | [[Dynamic blocks][Dynamic blocks]] | | A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | -| A | UNDERWAY | [[Org link types][Org link types]] | +| A | UNDERWAY | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | | B | UNDERWAY | [[Recursive queries][Recursive queries]] | | B | UNDERWAY | [[Timeline view][Timeline view]] | @@ -30,6 +33,19 @@ | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | #+END: +** To-do + +[[org-ql-search:%2528and%2520%2528todo%2520%2522TODO%2522%2529%2520%2528priority%2520%2522A%2522%2529%2529?sort=%2528priority%2529&title=%2522To-do%2520%255B%2523A%255D%2522][org-ql-search: To-do {#A}]] + +#+BEGIN: org-ql :query "todo:TODO priority:A" :columns (priority todo heading) :sort (priority date) :take 7 +| Priority | Todo | Heading | +|----------+------+--------------------------------------------------------------| +| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | +| A | TODO | [[Document sorters][Document sorters]] | +| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | +| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | +#+END: + * [#A] Tasks :PROPERTIES: :TOC: :include descendants :depth 1 @@ -49,7 +65,6 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] -- [[#dynamic-blocks][Dynamic blocks]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#outline-path-predicate][Outline path predicate]] - [[#recursive-queries][Recursive queries]] @@ -60,6 +75,7 @@ - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] - [[#group-tag-support][Group tag support]] +- [[#dynamic-blocks][Dynamic blocks]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] - [[#byte-compile-lambdas][Byte-compile lambdas]] @@ -194,13 +210,17 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test + Added example to =examples.org=. -*** UNDERWAY [#A] Org link types +*** UNDERWAY [#A] Org link types [2/3] :PROPERTIES: :ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e :END: This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. +**** TODO For saved queries + +**** DONE For searches + [2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: #+BEGIN_SRC org @@ -209,7 +229,7 @@ This would be useful for having a menu of saved queries as Org links, or even bo [2020-11-08 Sun 23:22] Seems to work! -#+BEGIN_SRC elisp +#+BEGIN_SRC elisp :results silent ;;;; Org link type ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. @@ -240,9 +260,103 @@ Tested on these queries: + [[org-ql-search:link:nullprogram]] #+END_SRC -**** TODO For all parameters +[2020-11-10 Tue 00:35] I'd like to support other parameters to the search, like grouping and sorting, so: -**** TODO For saved queries +#+BEGIN_SRC elisp :results silent + ;;;; Org link type + + ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. + + (org-link-set-parameters "org-ql-search" + :follow #'org-ql-search--link-open + :store #'org-ql-search--link-store) + + (defun org-ql-search--link-open (query) + "Open Org QL QUERY for current buffer." + (require 'url-parse) + (pcase-let* ((`(,query . ,params) + (url-path-and-query (url-parse-make-urlobj "org-ql-search" nil nil nil nil + query))) + (params (url-parse-query-string params)) + ;; Hacky or elegant? + (_ (mapc (lambda (pair) + (cl-callf (lambda (it) + (intern (concat ":" it))) + (car pair)) + (cl-callf read (cdr pair))) + params)) + (params (cl-loop for (key . value) in params + append (list key value)))) + (apply #'org-ql-search (current-buffer) query params))) + + (defun org-ql-search--link-store () + "Store a link to current Org QL query." + (when org-ql-view-query + (org-store-link-props :type "org-ql-search" + :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) + :description org-ql-view-title) + t)) +#+END_SRC + +That seems to work, like: + +#+BEGIN_SRC org + [[org-ql-search:property:author="Chris%20Wellons"?super-groups=((:auto-outline-path%20t))]] +#+END_SRC + +[2020-11-10 Tue 01:34] Okay, this seems to take care of all parameters: + +#+BEGIN_SRC elisp + (defun org-ql-search--link-open (path) + "Open Org QL query for current buffer at PATH. + PATH should be the part of an \"org-ql-search:\" URL after the + protocol. See, e.g. `org-ql-search--link-store'." + (require 'url-parse) + (require 'url-util) + (pcase-let* ((`(,query . ,params) (url-path-and-query + (url-parse-make-urlobj "org-ql-search" nil nil nil nil + path))) + (query (url-unhex-string query)) + (params (when params + (url-parse-query-string params))) + ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. + (sort (when (alist-get "sort" params nil nil #'string=) + (read (alist-get "sort" params nil nil #'string=)))) + (groups (when (alist-get "super-groups" params nil nil #'string=) + (read (alist-get "super-groups" params nil nil #'string=)))) + (title (when (alist-get "title" params nil nil #'string=) + (read (alist-get "title" params nil nil #'string=))))) + (org-ql-search (current-buffer) query + :sort sort + :super-groups groups + :title title))) + + (defun org-ql-search--link-store () + "Store a link to the current Org QL view. + Only views that search a single buffer may be linked to." + (require 'url-parse) + (require 'url-util) + (unless (or (bufferp org-ql-view-buffers-files) (= 1 (length org-ql-view-buffers-files))) + (user-error "Only views searching a single buffer may be linked")) + (when org-ql-view-query + (let* ((params (list (when org-ql-view-super-groups + (list "super-groups" (prin1-to-string org-ql-view-super-groups))) + (when org-ql-view-sort + (list "sort" (prin1-to-string org-ql-view-sort))) + (when org-ql-view-title + (list "title" (prin1-to-string org-ql-view-title))))) + (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) + "?" (url-build-query-string (delete nil params)))) + (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil + filename)))) + (org-store-link-props + :type "org-ql-search" + :link url + :description (concat "org-ql-search: " org-ql-view-title))) + t)) +#+END_SRC + +**** DONE For all parameters *** DONE Bookmarks diff --git a/org-ql-view.el b/org-ql-view.el index 30be96d..676b6c0 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -565,6 +565,68 @@ dates in the past, and negative for dates in the future." ;; more complicated and might introduce bugs elsewhere, so we'll just do this for now. (set-buffer (window-buffer (selected-window))))) +;;;; Links + +;; This section implements support for Org links to Org QL searches. Since the +;; links are stored from and opened in `org-ql-view' buffers, this section resides +;; in this file. However, since the links are to `org-ql-search' searches rather +;; than `org-ql-view' saved views, the link type is "org-ql-search". + +(org-link-set-parameters "org-ql-search" + :follow #'org-ql-view--link-open + :store #'org-ql-view--link-store) + +;; We require the URL libraries in the functions to hopefully avoid +;; loading them until they're needed. + +(defun org-ql-view--link-open (path) + "Open Org QL query for current buffer at PATH. +PATH should be the part of an \"org-ql-search:\" URL after the +protocol. See, e.g. `org-ql-view--link-store'." + (require 'url-parse) + (require 'url-util) + (pcase-let* ((`(,query . ,params) (url-path-and-query + (url-parse-make-urlobj "org-ql-search" nil nil nil nil + path))) + (query (url-unhex-string query)) + (params (when params (url-parse-query-string params))) + ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. + (sort (--when-let (alist-get "sort" params nil nil #'string=) + (read it))) + (groups (--when-let (alist-get "super-groups" params nil nil #'string=) + (read it))) + (title (--when-let (alist-get "title" params nil nil #'string=) + (read it)))) + (org-ql-search (current-buffer) query + :sort sort + :super-groups groups + :title title))) + +(defun org-ql-view--link-store () + "Store a link to the current Org QL view. +When opened, the link searches the buffer it's opened from." + (require 'url-parse) + (require 'url-util) + (unless (or (bufferp org-ql-view-buffers-files) + (= 1 (length org-ql-view-buffers-files))) + (user-error "Only views searching a single buffer may be linked")) + (when org-ql-view-query + (let* ((params (list (when org-ql-view-super-groups + (list "super-groups" (prin1-to-string org-ql-view-super-groups))) + (when org-ql-view-sort + (list "sort" (prin1-to-string org-ql-view-sort))) + (when org-ql-view-title + (list "title" (prin1-to-string org-ql-view-title))))) + (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) + "?" (url-build-query-string (delete nil params)))) + (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil + filename)))) + (org-store-link-props + :type "org-ql-search" + :link url + :description (concat "org-ql-search: " org-ql-view-title))) + t)) + ;;;; Transient ;; This section uses `transient' to allow the user to easily modify diff --git a/org-ql.info b/org-ql.info index afe4e3a..e54d655 100644 --- a/org-ql.info +++ b/org-ql.info @@ -36,6 +36,7 @@ Usage * Queries:: * Functions / Macros:: * Dynamic block:: +* Links:: * Tips:: Commands @@ -155,7 +156,7 @@ File: README.info, Node: Usage, Next: Changelog, Prev: Installation, Up: Top ******* • • - • • • • • • • + • • • • • • • • Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -167,6 +168,7 @@ and polished, they will be considered stable. * Queries:: * Functions / Macros:: * Dynamic block:: +* Links:: * Tips::  @@ -713,7 +715,7 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, For convenience, arguments should be unquoted.  -File: README.info, Node: Dynamic block, Next: Tips, Prev: Functions / Macros, Up: Usage +File: README.info, Node: Dynamic block, Next: Links, Prev: Functions / Macros, Up: Usage 4.4 Dynamic block ================= @@ -753,9 +755,30 @@ with certain columns and timestamp format: #+END:  -File: README.info, Node: Tips, Prev: Dynamic block, Up: Usage +File: README.info, Node: Links, Next: Tips, Prev: Dynamic block, Up: Usage -4.5 Tips +4.5 Links +========= + +Org QL View searches may be accessed by opening ‘org-ql-search:’ links +in an Org file. + + In an Org QL View buffer, the command ‘org-store-link’ (i.e. ‘C-c +l’) stores a link to the current search, and it may be inserted into an +Org buffer with the command ‘org-insert-link’ (‘C-c C-l’). The stored +link records all of the view settings, like title, sorting, and +grouping. + + Simple links may also be written manually in either sexp or non-sexp +form, like: + + [[org-ql-search:todo:NEXT priority:A]] + [[org-ql-search:(and (todo "NEXT") (priority "A"))]] + + +File: README.info, Node: Tips, Prev: Links, Up: Usage + +4.6 Tips ======== • Org QL View buffers can be bookmarked with Emacs bookmark commands, @@ -810,6 +833,8 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog view restoration with Burly (https://github.com/alphapapa/burly.el).) • Dynamic block support. + • Org link support (storing and opening links to Org QL View searches + in the current document). • Mascot. *Changed* @@ -1231,49 +1256,50 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1539 -Node: Screenshots1662 -Node: Installation1780 -Node: Quelpa2418 -Node: Usage2861 -Node: Commands3245 -Node: org-ql-search3718 -Node: helm-org-ql5432 -Node: org-ql-view5844 -Node: org-ql-view-sidebar6344 -Node: org-ql-view-recent-items6700 -Node: org-ql-sparse-tree7184 -Node: Queries7984 -Node: Non-sexp query syntax8892 -Node: General predicates10599 -Node: Ancestor/descendant predicates15814 -Node: Date/time predicates16942 -Node: Functions / Macros19597 -Node: Agenda-like views19852 -Node: Listing / acting-on results21257 -Node: Dynamic block25859 -Node: Tips27885 -Node: Changelog28211 -Node: 05-pre28850 -Node: 04629726 -Node: 04530129 -Node: 04430488 -Node: 04330845 -Node: 04231040 -Node: 04131199 -Node: 0431438 -Node: 03235369 -Node: 03135746 -Node: 0335943 -Node: 02338918 -Node: 02239146 -Node: 02139414 -Node: 0239613 -Node: 0143648 -Node: Notes43749 -Node: Comparison with Org Agenda searches43911 -Node: org-sidebar44783 -Node: License45062 +Node: Contents1549 +Node: Screenshots1672 +Node: Installation1790 +Node: Quelpa2428 +Node: Usage2871 +Node: Commands3269 +Node: org-ql-search3742 +Node: helm-org-ql5456 +Node: org-ql-view5868 +Node: org-ql-view-sidebar6368 +Node: org-ql-view-recent-items6724 +Node: org-ql-sparse-tree7208 +Node: Queries8008 +Node: Non-sexp query syntax8916 +Node: General predicates10623 +Node: Ancestor/descendant predicates15838 +Node: Date/time predicates16966 +Node: Functions / Macros19621 +Node: Agenda-like views19876 +Node: Listing / acting-on results21281 +Node: Dynamic block25883 +Node: Links27910 +Node: Tips28597 +Node: Changelog28915 +Node: 05-pre29554 +Node: 04630536 +Node: 04530939 +Node: 04431298 +Node: 04331655 +Node: 04231850 +Node: 04132009 +Node: 0432248 +Node: 03236179 +Node: 03136556 +Node: 0336753 +Node: 02339728 +Node: 02239956 +Node: 02140224 +Node: 0240423 +Node: 0144458 +Node: Notes44559 +Node: Comparison with Org Agenda searches44721 +Node: org-sidebar45593 +Node: License45872  End Tag Table From 9bdfcc1d3d9e91fc3c01243fd97c827d81b04c67 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 02:28:44 -0600 Subject: [PATCH 156/560] Add: (org-dblock-write:org-ql) Custom column headers --- README.org | 21 ++++++++------- notes.org | 36 ++++++++++++------------- org-ql-search.el | 29 +++++++++++++------- org-ql.info | 69 +++++++++++++++++++++++++----------------------- 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/README.org b/README.org index 59bbb23..a4ee176 100644 --- a/README.org +++ b/README.org @@ -404,6 +404,7 @@ Org QL provides a dynamic block that lists entries in the current document match + ~:query~: An Org QL query expression in either sexp or non-sexp form. + ~:columns~ A list of columns, including ~heading~, ~todo~, ~priority~, ~deadline~, ~scheduled~. + - Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the priority column: ~(priority "P")~ + ~:sort~ One or a list of Org QL sorting methods (see ~org-ql-select~). + ~:take~ Optionally take a number of results from the front (a positive number) or the end (a negative number) of the results. + ~:ts-format~ Optional format string used to format timestamp-based columns. @@ -415,16 +416,16 @@ For example, this dynamic block shows the first seven headings that are to-do it # NOTE: These results are edited manually because the Org links don't display well in the Info manual. #+BEGIN_SRC org - ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | Priority | Deadline | Heading | - |------+----------+------------------+---------------------------------------| - | TODO | A | 2017-07-07 00:00 | Take over the world | - | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | - | TODO | A | 2017-07-15 00:00 | Take over the universe | - | TODO | B | 2017-07-21 00:00 | Internet | - | TODO | A | 2017-08-01 00:00 | Spaceship lease | - | TODO | A | | Skype with president of Antarctica | - | TODO | B | | Take over Mars | + ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Deadline | Heading | + |------+---+------------------+---------------------------------------| + | TODO | A | 2017-07-07 00:00 | Take over the world | + | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | 2017-07-15 00:00 | Take over the universe | + | TODO | B | 2017-07-21 00:00 | Internet | + | TODO | A | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | Skype with president of Antarctica | + | TODO | B | | Take over Mars | ,#+END: #+END_SRC diff --git a/notes.org b/notes.org index 78d8c32..aa33ceb 100644 --- a/notes.org +++ b/notes.org @@ -20,30 +20,30 @@ [[org-ql-search:%2528todo%2520%2522UNDERWAY%2522%2529?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] -#+BEGIN: org-ql :query (todo "UNDERWAY") :columns (priority todo heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" -| Priority | Todo | Heading | -|----------+----------+--------------------------------------------------------------------| -| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | -| A | UNDERWAY | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | -| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | -| B | UNDERWAY | [[Recursive queries][Recursive queries]] | -| B | UNDERWAY | [[Timeline view][Timeline view]] | -| B | UNDERWAY | [["Node" caching]["Node" caching]] | -| B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | -| | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | +#+BEGIN: org-ql :query (todo "UNDERWAY") :columns ((priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +| P | Keyword | Heading | +|---+----------+--------------------------------------------------------------------| +| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | +| A | UNDERWAY | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | +| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | +| B | UNDERWAY | [[Recursive queries][Recursive queries]] | +| B | UNDERWAY | [[Timeline view][Timeline view]] | +| B | UNDERWAY | [["Node" caching]["Node" caching]] | +| B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | +| | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | #+END: ** To-do [[org-ql-search:%2528and%2520%2528todo%2520%2522TODO%2522%2529%2520%2528priority%2520%2522A%2522%2529%2529?sort=%2528priority%2529&title=%2522To-do%2520%255B%2523A%255D%2522][org-ql-search: To-do {#A}]] -#+BEGIN: org-ql :query "todo:TODO priority:A" :columns (priority todo heading) :sort (priority date) :take 7 -| Priority | Todo | Heading | -|----------+------+--------------------------------------------------------------| -| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | -| A | TODO | [[Document sorters][Document sorters]] | -| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | -| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | +#+BEGIN: org-ql :query "todo:TODO priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 +| P | Todo | Heading | +|---+------+--------------------------------------------------------------| +| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | +| A | TODO | [[Document sorters][Document sorters]] | +| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | +| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | #+END: * [#A] Tasks diff --git a/org-ql-search.el b/org-ql-search.el index f9506f2..e319562 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -242,17 +242,24 @@ automatically from the query." "Insert content for org-ql dynamic block at point according to PARAMS. Valid parameters include: - :query An Org QL query expression in either sexp or non-sexp form. + :query An Org QL query expression in either sexp or non-sexp + form. :columns A list of columns, including `heading', `todo', - `priority', `deadline', `scheduled'. + `priority', `deadline', `scheduled'. Each column may + also be specified as a list with the second element + being a header string. For example, to abbreviate + the priority column: (priority \"P\") - :sort One or a list of Org QL sorting methods (see `org-ql-select'). + :sort One or a list of Org QL sorting methods + (see `org-ql-select'). - :take Optionally take a number of results from the front (a - positive number) or the end (a negative number) of the results. + :take Optionally take a number of results from the front (a + positive number) or the end (a negative number) of + the results. - :ts-format Optional format string used to format timestamp-based columns. + :ts-format Optional format string used to format + timestamp-based columns. For example, an org-ql dynamic block header could look like: @@ -261,7 +268,7 @@ For example, an org-ql dynamic block header could look like: (query (cl-etypecase query (string (org-ql--plain-query query)) (t query))) - (columns (or columns '(heading todo priority))) + (columns (or columns '(heading todo (priority "P")))) ;; MAYBE: Custom column functions. (format-fns ;; NOTE: Backquoting this alist prevents the lambdas from seeing @@ -290,11 +297,15 @@ For example, an org-ql dynamic block header could look like: (integer (-take take elements))))) (cl-labels ((format-element (element) (string-join (cl-loop for column in columns - for fn = (alist-get column format-fns) + for fn = (cl-etypecase column + (symbol (alist-get column format-fns)) + (list (alist-get (car column) format-fns))) collect (or (funcall fn element) "")) " | "))) ;; Insert table header. - (insert "| " (string-join (--map (capitalize (symbol-name it)) + (insert "| " (string-join (--map (pcase it + ((pred symbolp) (capitalize (symbol-name it))) + (`(,_ ,name) name)) columns) " | ") " |" "\n") diff --git a/org-ql.info b/org-ql.info index e54d655..69af6fe 100644 --- a/org-ql.info +++ b/org-ql.info @@ -728,6 +728,9 @@ supported: form. • ‘:columns’ A list of columns, including ‘heading’, ‘todo’, ‘priority’, ‘deadline’, ‘scheduled’. + • Each column may also be specified as a list with the second + element being a header string. For example, to abbreviate the + priority column: ‘(priority "P")’ • ‘:sort’ One or a list of Org QL sorting methods (see ‘org-ql-select’). • ‘:take’ Optionally take a number of results from the front (a @@ -742,16 +745,16 @@ in the following example). are to-do items with priority A or B, sorted by deadline then priority, with certain columns and timestamp format: - #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo priority deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | Priority | Deadline | Heading | - |------+----------+------------------+---------------------------------------| - | TODO | A | 2017-07-07 00:00 | Take over the world | - | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | - | TODO | A | 2017-07-15 00:00 | Take over the universe | - | TODO | B | 2017-07-21 00:00 | Internet | - | TODO | A | 2017-08-01 00:00 | Spaceship lease | - | TODO | A | | Skype with president of Antarctica | - | TODO | B | | Take over Mars | + #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Deadline | Heading | + |------+---+------------------+---------------------------------------| + | TODO | A | 2017-07-07 00:00 | Take over the world | + | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | 2017-07-15 00:00 | Take over the universe | + | TODO | B | 2017-07-21 00:00 | Internet | + | TODO | A | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | Skype with president of Antarctica | + | TODO | B | | Take over Mars | #+END:  @@ -1277,29 +1280,29 @@ Node: Functions / Macros19621 Node: Agenda-like views19876 Node: Listing / acting-on results21281 Node: Dynamic block25883 -Node: Links27910 -Node: Tips28597 -Node: Changelog28915 -Node: 05-pre29554 -Node: 04630536 -Node: 04530939 -Node: 04431298 -Node: 04331655 -Node: 04231850 -Node: 04132009 -Node: 0432248 -Node: 03236179 -Node: 03136556 -Node: 0336753 -Node: 02339728 -Node: 02239956 -Node: 02140224 -Node: 0240423 -Node: 0144458 -Node: Notes44559 -Node: Comparison with Org Agenda searches44721 -Node: org-sidebar45593 -Node: License45872 +Node: Links28046 +Node: Tips28733 +Node: Changelog29051 +Node: 05-pre29690 +Node: 04630672 +Node: 04531075 +Node: 04431434 +Node: 04331791 +Node: 04231986 +Node: 04132145 +Node: 0432384 +Node: 03236315 +Node: 03136692 +Node: 0336889 +Node: 02339864 +Node: 02240092 +Node: 02140360 +Node: 0240559 +Node: 0144594 +Node: Notes44695 +Node: Comparison with Org Agenda searches44857 +Node: org-sidebar45729 +Node: License46008  End Tag Table From 6d5ce97dc7725bf6602a29d5f64b3b1ff06c3df7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 04:14:01 -0600 Subject: [PATCH 157/560] Fix: Byte-compile warnings --- org-ql-view.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 676b6c0..b0f47a3 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -398,6 +398,8 @@ update search arguments." insert)) (current-buffer))) +(defvar bookmark-make-record-function) + (cl-defun org-ql-view--display (&key (buffer org-ql-view-buffer) header string) "Display STRING in `org-ql-view' BUFFER. @@ -521,8 +523,7 @@ dates in the past, and negative for dates in the future." ;; Support for Emacs bookmarks. -(eval-when-compile - (require 'bookmark)) +(require 'bookmark) (defun org-ql-view--bookmark-make-record () "Return a bookmark record for the current Org QL View buffer." From 2e469fa5475510dbce683399c95ac70f4e79698e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 04:14:44 -0600 Subject: [PATCH 158/560] Tidy: (org-ql--peg-parse-string) Silence, Checkdoc! --- org-ql.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 4e4e5fd..d0c2fe5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1672,9 +1672,12 @@ element should be a regexp string." (defvar peg-stack nil) (defmacro org-ql--peg-parse-string (rules string &optional noerror) - "Parse STRING according to RULES. -If NOERROR is non-nil, push nil resp. t if the parse failed -resp. succeded instead of signaling an error." + "Parse STRING according to RULES." + ;; This sentence was in the docstring but Checkdoc is complaining, + ;; so moving it to a comment: "If NOERROR is non-nil, push nil + ;; resp. t if the parse failed resp. succeded instead of signaling + ;; an error." + ;; Unfortunately, this macro was moved to peg-tests.el, so we copy it here. `(with-temp-buffer (insert ,string) From 0cfe44084bf639dcf51bb65b432d55e22424f84c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 04:24:38 -0600 Subject: [PATCH 159/560] Tidy: (org-dblock-write:org-ql) --- org-ql-search.el | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index e319562..bb02545 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -273,11 +273,11 @@ For example, an org-ql dynamic block header could look like: (format-fns ;; NOTE: Backquoting this alist prevents the lambdas from seeing ;; the variable `ts-format', so we use `list' and `cons'. - (list (cons 'heading (lambda (element) + (list (cons 'todo (lambda (element) + (org-element-property :todo-keyword element))) + (cons 'heading (lambda (element) (org-make-link-string (org-element-property :raw-value element) (org-element-property :raw-value element)))) - (cons 'todo (lambda (element) - (org-element-property :todo-keyword element))) (cons 'priority (lambda (element) (--when-let (org-element-property :priority element) (char-to-string it)))) @@ -302,19 +302,16 @@ For example, an org-ql dynamic block header could look like: (list (alist-get (car column) format-fns))) collect (or (funcall fn element) "")) " | "))) - ;; Insert table header. + ;; Table header (insert "| " (string-join (--map (pcase it ((pred symbolp) (capitalize (symbol-name it))) (`(,_ ,name) name)) columns) " | ") " |" "\n") - ;; Separator line. - (insert "|- \n") - ;; Elements. + (insert "|- \n") ; Separator hline (dolist (element elements) (insert "| " (format-element element) " |" "\n")) - ;; Delete final newline and align table. (delete-char -1) (org-table-align)))) From 0b65eb221e16dfeb3ae8cee5c1578872c7903860 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 04:32:21 -0600 Subject: [PATCH 160/560] Notes: Add TODO --- notes.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/notes.org b/notes.org index aa33ceb..baf6dbc 100644 --- a/notes.org +++ b/notes.org @@ -83,6 +83,7 @@ - [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] - [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] - [[#use-macros-for-date][Use macros for date]] +- [[#save-views-to-dynamic-blocks][Save views to dynamic blocks]] :END: ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate @@ -101,6 +102,10 @@ Note that the built-in sorting only works on Org elements, which is the default For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. +** TODO [#A] Save views to dynamic blocks + +[2020-11-10 Tue 04:31] A command would save users from having to write out the dynamic block manually. + ** TODO [#B] Outline path in buffers-files arg :PROPERTIES: :ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 From 5a0ed259bcb967067e24815c3e969f39dd02ee87 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 05:21:56 -0600 Subject: [PATCH 161/560] Notes: Add TODO --- notes.org | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/notes.org b/notes.org index baf6dbc..308274b 100644 --- a/notes.org +++ b/notes.org @@ -55,6 +55,8 @@ - [[#document-sorters][Document sorters]] - [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] +- [[#save-views-to-dynamic-blocks][Save views to dynamic blocks]] +- [[#consider-how-to-secure-searches-from-links-and-dynamic-blocks][Consider how to "secure" searches from links and dynamic blocks]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] - [[#add-more-sorters][Add more sorters?]] - [[#default-sort][Default sort]] @@ -83,7 +85,6 @@ - [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] - [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] - [[#use-macros-for-date][Use macros for date]] -- [[#save-views-to-dynamic-blocks][Save views to dynamic blocks]] :END: ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate @@ -106,6 +107,17 @@ For consistency, because plain ~auto~ looks like a variable, and even though it' [2020-11-10 Tue 04:31] A command would save users from having to write out the dynamic block manually. +** TODO [#A] Consider how to "secure" searches from links and dynamic blocks + +Theoretically one could put a sexp-based query into a link that would run arbitrary code to do something evil. Like: + +[[org-ql-search:(message "AHA")]] + +That's very unlikely to be abused, but it would be good to protect against it. Two possibilities: + +1. For sexp-based queries in links and dynamic blocks, prompt for confirmation before running. +2. Use a special variable to control whether lambdas and arbitrary sexps are allowed in queries, and disable it for links and dynamic blocks. (That might be difficult to do, since they could be buried in an ~and~ or something. A whitelist approach might be needed.) + ** TODO [#B] Outline path in buffers-files arg :PROPERTIES: :ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 From 1b43a88d32ab552e3922bda89a454afdc557d8d0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 17:45:27 -0600 Subject: [PATCH 162/560] Fix: (org-ql-view--link-store) Check buffers-files only when needed See #147. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index b0f47a3..fb3c865 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -608,10 +608,10 @@ protocol. See, e.g. `org-ql-view--link-store'." When opened, the link searches the buffer it's opened from." (require 'url-parse) (require 'url-util) - (unless (or (bufferp org-ql-view-buffers-files) - (= 1 (length org-ql-view-buffers-files))) - (user-error "Only views searching a single buffer may be linked")) (when org-ql-view-query + (unless (or (bufferp org-ql-view-buffers-files) + (= 1 (length org-ql-view-buffers-files))) + (user-error "Only views searching a single buffer may be linked")) (let* ((params (list (when org-ql-view-super-groups (list "super-groups" (prin1-to-string org-ql-view-super-groups))) (when org-ql-view-sort From 5d563809e22aed7d8d50995b034557035a95ffd7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 18:24:49 -0600 Subject: [PATCH 163/560] Change: (-view--link-open, -view--link-store) Links to views of files Fixes #147. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index fb3c865..525642d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -597,8 +597,10 @@ protocol. See, e.g. `org-ql-view--link-store'." (groups (--when-let (alist-get "super-groups" params nil nil #'string=) (read it))) (title (--when-let (alist-get "title" params nil nil #'string=) - (read it)))) - (org-ql-search (current-buffer) query + (read it))) + (buffers-files (--when-let (alist-get "buffers-files" params nil nil #'string=) + (read it)))) + (org-ql-search buffers-files query :sort sort :super-groups groups :title title))) @@ -610,9 +612,12 @@ When opened, the link searches the buffer it's opened from." (require 'url-util) (when org-ql-view-query (unless (or (bufferp org-ql-view-buffers-files) - (= 1 (length org-ql-view-buffers-files))) - (user-error "Only views searching a single buffer may be linked")) - (let* ((params (list (when org-ql-view-super-groups + (and (listp org-ql-view-buffers-files) + (cl-every #'file-exists-p org-ql-view-buffers-files))) + (user-error "Can only store links to views of either a single buffer or a list of files")) + (let* ((params (list (when org-ql-view-buffers-files + (list "buffers-files" (prin1-to-string org-ql-view-buffers-files))) + (when org-ql-view-super-groups (list "super-groups" (prin1-to-string org-ql-view-super-groups))) (when org-ql-view-sort (list "sort" (prin1-to-string org-ql-view-sort))) From e3c7aaf98d9226410dd1d45456388b878e69e4d1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 18:37:04 -0600 Subject: [PATCH 164/560] Docs: (org-ql-search) Add Info links to docstring --- org-ql-search.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index bb02545..c771a08 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -121,17 +121,18 @@ Interactively, may also be: - An expression which evaluates to a list of files/buffers - A space-separated list of file or buffer names -QUERY: An `org-ql' query in either sexp or \"plain string\" -form (see documentation). +QUERY: An `org-ql' query in either sexp or non-sexp form (see +Info node `(org-ql)Queries'). SUPER-GROUPS: An `org-super-agenda' group set. See variable -`org-super-agenda-groups'. +`org-super-agenda-groups' and Info node `(org-super-agenda)Group +selectors'. NARROW: When non-nil, don't widen buffers before searching. Interactively, with prefix, leave narrowed. SORT: One or a list of `org-ql' sorting functions, like `date' or -`priority'. +`priority' (see Info node `(org-ql)Listing / acting-on results'). TITLE: An optional string displayed in the header. From 364dfabca45cc8b5778b602a67c5b6528ef19af6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 19:17:14 -0600 Subject: [PATCH 165/560] Add: (org-ql-view-ask-unsafe-links) --- org-ql-view.el | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index 525642d..8eb914a 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -98,6 +98,23 @@ Based on `org-agenda-mode-map'.") "Options for `org-ql-view'." :group 'org-ql) +(defcustom org-ql-view-ask-unsafe-links t + "Ask before opening a link that could run arbitrary code. +Org QL queries in sexp form can contain arbitrary expressions. +When opening an \"org-ql-search:\" link that contains a query in +sexp form, and this option is non-nil, the user will be prompted +for confirmation before opening the link. + +This variable may be set file-locally to disable this warning in +files that the user assumes are safe (e.g. of known provenance). +Users who are entirely unconcerned about this issue may disable +the option globally (at their own risk, however minimal it +probably is). + +See Info node `(org-ql)Queries'." + :type 'boolean + :risky t) + (defcustom org-ql-view-display-buffer-action nil "Action argument passed through `pop-to-buffer' to `display-buffer', which see." :type '(cons function alist)) @@ -600,6 +617,18 @@ protocol. See, e.g. `org-ql-view--link-store'." (read it))) (buffers-files (--when-let (alist-get "buffers-files" params nil nil #'string=) (read it)))) + (when (and org-ql-view-ask-unsafe-links + (or (string-match (rx bol (0+ space) "(") query) + (listp query))) + ;; Query is in sexp form: ask for confirmation, because it could contain arbitrary code. + (let ((query-string (propertize (cl-etypecase query + (list (prin1-to-string query)) + (string query)) + ;; FIXME: The face doesn't seem to be displayed. + 'face 'font-lock-warning-face))) + (unless (yes-or-no-p (concat "Query is in sexp form and could contain arbitrary code: " + query-string " Execute it? ")) + (user-error "Query aborted by user")))) (org-ql-search buffers-files query :sort sort :super-groups groups From 93f60ad4783d115728edb3825a53929f59b4b5bc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 19:30:46 -0600 Subject: [PATCH 166/560] Fix: (org-ql-view--link-store) Handle single filenames Fixes #147. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index 8eb914a..e83cbc6 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -641,9 +641,10 @@ When opened, the link searches the buffer it's opened from." (require 'url-util) (when org-ql-view-query (unless (or (bufferp org-ql-view-buffers-files) + (file-exists-p org-ql-view-buffers-files) (and (listp org-ql-view-buffers-files) (cl-every #'file-exists-p org-ql-view-buffers-files))) - (user-error "Can only store links to views of either a single buffer or a list of files")) + (user-error "Can only store links to views of either a single buffer/file or a list of files")) (let* ((params (list (when org-ql-view-buffers-files (list "buffers-files" (prin1-to-string org-ql-view-buffers-files))) (when org-ql-view-super-groups From 60b457eea4b5d72a4b0b8e7df7c617c1b21ae99f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 19:43:48 -0600 Subject: [PATCH 167/560] Fix: (org-ql-view.el) Compiler warnings --- org-ql-view.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index e83cbc6..641221e 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -597,6 +597,10 @@ dates in the past, and negative for dates in the future." ;; We require the URL libraries in the functions to hopefully avoid ;; loading them until they're needed. +(eval-when-compile + (require 'url-parse) + (require 'url-util)) + (defun org-ql-view--link-open (path) "Open Org QL query for current buffer at PATH. PATH should be the part of an \"org-ql-search:\" URL after the From 23e73addcfe774e6979ce684e4fea101d25bed8f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 20:34:39 -0600 Subject: [PATCH 168/560] Fix: (-view--link-store, -view--link-open) Types, current-buffer This is regrettably complicated. Maybe someday Elsa will help... Fixes #147 (again). Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 641221e..8875499 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -619,8 +619,9 @@ protocol. See, e.g. `org-ql-view--link-store'." (read it))) (title (--when-let (alist-get "title" params nil nil #'string=) (read it))) - (buffers-files (--when-let (alist-get "buffers-files" params nil nil #'string=) - (read it)))) + (buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=) + (read it) + (current-buffer)))) (when (and org-ql-view-ask-unsafe-links (or (string-match (rx bol (0+ space) "(") query) (listp query))) @@ -644,12 +645,18 @@ When opened, the link searches the buffer it's opened from." (require 'url-parse) (require 'url-util) (when org-ql-view-query - (unless (or (bufferp org-ql-view-buffers-files) - (file-exists-p org-ql-view-buffers-files) - (and (listp org-ql-view-buffers-files) - (cl-every #'file-exists-p org-ql-view-buffers-files))) + (unless (cl-etypecase org-ql-view-buffers-files + ;; I really wish `anaphora' were in ELPA, because `aetypecase' would be + ;; nice here, and I'd prefer to avoid adding more MELPA-only dependencies. + (buffer t) + (string (file-exists-p org-ql-view-buffers-files)) + (list (and (cl-every #'stringp org-ql-view-buffers-files) + (cl-every #'file-exists-p org-ql-view-buffers-files)))) (user-error "Can only store links to views of either a single buffer/file or a list of files")) - (let* ((params (list (when org-ql-view-buffers-files + (let* ((params (list (when (and org-ql-view-buffers-files + ;; If it's one buffer (i.e. the view searches the current + ;; buffer), don't serialize it, because buffers are unreadable. + (not (bufferp org-ql-view-buffers-files))) (list "buffers-files" (prin1-to-string org-ql-view-buffers-files))) (when org-ql-view-super-groups (list "super-groups" (prin1-to-string org-ql-view-super-groups))) From 78fd672cc7c474bc99b40bdee37ca6b8c75546d3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 00:21:19 -0600 Subject: [PATCH 169/560] Fix: (org-ql-view--format-element) Get tags from marker buffer Fixes bug introduced in 359a280d11d54c940125f11d7be6a93f8c0c1095. Fixes #150. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 8875499..cd6ccbb 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -837,10 +837,12 @@ return an empty string." ;; MAYBE: Use our own variable instead of `org-use-tag-inheritance'. (if-let ((marker (or (org-element-property :org-hd-marker element) (org-element-property :org-marker element)))) - (cl-loop for type in (org-ql--tags-at marker) - unless (or (eq 'org-ql-nil type) - (not type)) - append type) + (with-current-buffer (marker-buffer marker) + (org-with-wide-buffer + (cl-loop for type in (org-ql--tags-at marker) + unless (or (eq 'org-ql-nil type) + (not type)) + append type))) ;; No marker found ;; TODO: Use `display-warning' with `org-ql' as the type. (warn "No marker found for item: %s" title) From 73da48d9da68079ca9cbcfcaa8ace23a51f8d5ee Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 00:21:56 -0600 Subject: [PATCH 170/560] Comment: Add FIXMEs --- org-ql.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org-ql.el b/org-ql.el index d0c2fe5..c638f4d 100644 --- a/org-ql.el +++ b/org-ql.el @@ -393,6 +393,7 @@ If NARROW is non-nil, buffer will not be widened." ;;;;; Helpers (defun org-ql--tags-at (position) + ;; FIXME: This function actually assumes that point is already at POSITION. "Return tags for POSITION in current buffer. Returns cons (INHERITED-TAGS . LOCAL-TAGS)." ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables @@ -404,6 +405,9 @@ Returns cons (INHERITED-TAGS . LOCAL-TAGS)." (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) (cached-result (gethash position tags-cache))) ;; Found in cache: return them. + ;; FIXME: Isn't `cached-result' a list of (INHERITED . LOCAL)? It + ;; will never be just `org-ql-nil', but the CAR and CDR may be, so + ;; they need to each be checked and replaced with nil if necessary. (pcase cached-result ('org-ql-nil nil) (_ cached-result)) From bd9162381f17539b7772d0506292fb6f1aebf335 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 01:45:55 -0600 Subject: [PATCH 171/560] Notes: Update --- notes.org | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 8 deletions(-) diff --git a/notes.org b/notes.org index 308274b..d7ff1d5 100644 --- a/notes.org +++ b/notes.org @@ -35,15 +35,18 @@ ** To-do -[[org-ql-search:%2528and%2520%2528todo%2520%2522TODO%2522%2529%2520%2528priority%2520%2522A%2522%2529%2529?sort=%2528priority%2529&title=%2522To-do%2520%255B%2523A%255D%2522][org-ql-search: To-do {#A}]] +[[org-ql-search:todo:?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529][org-ql-search: Tasks]] -#+BEGIN: org-ql :query "todo:TODO priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 -| P | Todo | Heading | -|---+------+--------------------------------------------------------------| -| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | -| A | TODO | [[Document sorters][Document sorters]] | -| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | -| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | +#+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 +| P | Todo | Heading | +|---+----------+-----------------------------------------------------------------| +| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | +| A | TODO | [[Document sorters][Document sorters]] | +| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | +| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | +| A | TODO | [[Save views to dynamic blocks][Save views to dynamic blocks]] | +| A | TODO | [[Consider how to "secure" searches from links and dynamic blocks][Consider how to "secure" searches from links and dynamic blocks]] | +| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | #+END: * [#A] Tasks @@ -67,6 +70,7 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] +- [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#outline-path-predicate][Outline path predicate]] - [[#recursive-queries][Recursive queries]] @@ -223,6 +227,100 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary +** UNDERWAY [#A] Convert simple sexp queries to non-sexp + +[2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... + +#+BEGIN_SRC elisp + (defun org-ql--query-sexp-to-plain (query) + "Return a plain query string for sexp QUERY. + If QUERY can't be converted to a plain one, return nil." + ;; This started out pretty simple...but at least it's not just one long function, right? + (cl-labels ((complex-p (query) + (or (contains-p 'or query))) + (contains-p (symbol list) + (cl-loop for element in list + thereis (or (eq symbol element) + (and (listp element) + (contains-p symbol element))))) + (format-args + (args) (let (non-paired paired next-keyword) + (cl-loop for arg in args + do (cond (next-keyword (push (cons next-keyword arg) paired) + (setf next-keyword nil)) + ((keywordp arg) (setf next-keyword (substring (symbol-name arg) 1))) + (t (push arg non-paired)))) + (string-join (append (mapcar #'format-atom non-paired) + (nreverse (--map (format "%s=%s" (car it) (cdr it)) + paired))) + ","))) + (format-atom + (atom) (cl-typecase atom + (string (if (string-match (rx space) atom) + (format "%S" atom) + (format "%s" atom))) + (t (format "%s" atom)))) + (format-form + (form) (pcase form + (`(not . (,rest)) (concat "!" (format-form rest))) + (`(priority . ,_) (format-priority form)) + ;; FIXME: Convert (src) queries to non-sexp form...someday... + (`(src . ,_) (user-error "Converting (src ...) queries to non-sexp form is not implemented")) + (_ (pcase-let* ((`(,pred . ,args) form) + (args-string (pcase args + ('() "") + ((guard (= 1 (length args))) (format "%s" (car args))) + (_ (format-args args))))) + (format "%s:%s" pred args-string))))) + (format-and + (form) (pcase-let* ((`(and . ,rest) form)) + (string-join (mapcar #'format-form rest) " "))) + (format-priority + (form) (pcase-let* ((`(priority . ,rest) form) + (args (pcase rest + (`(,(and comparator (or < <= > >= =)) ,letter) + (priority-letters comparator letter)) + (_ rest)))) + (concat "priority:" (string-join args ",")))) + (priority-letters + (comparator letter) (let* ((char (string-to-char (upcase (symbol-name letter)))) + (numeric-priorities '(?A ?B ?C)) + ;; NOTE: The comparator inversion is intentional. + (others (pcase comparator + ('< (--select (> it char) numeric-priorities)) + ('<= (--select (>= it char) numeric-priorities)) + ('> (--select (< it char) numeric-priorities)) + ('>= (--select (<= it char) numeric-priorities)) + ('= (--select (= it char) numeric-priorities))))) + (mapcar #'char-to-string others)))) + (unless (complex-p query) + (pcase query + (`(and . ,_) (format-and query)) + (_ (format-form query)))))) + + (--map (cons it (org-ql--query-sexp-to-plain it)) + '((priority >= B) + (priority > B) + (priority < B) + (priority < A) + (priority = A) + (todo) + (todo "TODO") + (todo "TODO" "NEXT") + (ts :from -1 :to 1) + (ts :on today) + (ts-active :from "2017-01-01" :to "2018-01-01") + (heading "quoted phrase" "word") + (and (tags "book" "books") (priority "A")) + (and (tags "space") (not (regexp "moon"))) + (src :lang "elisp" :regexps ("defun"))) + + + ) +#+END_SRC + +[2020-11-11 Wed 01:45] Seems to work well. Now to integrate that into link-saving... + ** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + Added example to =examples.org=. From 168041f0df7c425c9833c6f2c363d1f0b38daef5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 04:22:21 -0600 Subject: [PATCH 172/560] Comment: Add FIXME --- org-ql-view.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index cd6ccbb..823d426 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -566,6 +566,9 @@ dates in the past, and negative for dates in the future." ;;;###autoload (defun org-ql-view--bookmark-handler (bookmark) "Show Org QL View BOOKMARK in current buffer." + ;; FIXME: Getting "(void-variable super-groups)" errors when this function is byte-compiled, + ;; but not when it's interpreted! Using (:super-groups super-groups) instead of just + ;; :super-groups fixes it, but I have no idea why, and the macroexpansion is the same. (pcase-let* (((map org-ql-view-plist) (bookmark-get-bookmark-record bookmark)) ((map :buffers-files :query :super-groups :narrow :sort :title) org-ql-view-plist) From 8102d7a8ee18fb593076d01abd3323d024cb5a7d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 18:11:24 -0600 Subject: [PATCH 173/560] Fix: (org-ql-view--format-element) Actually, really fix it this time. Fixes #150. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-view.el b/org-ql-view.el index 823d426..087ff77 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -842,6 +842,7 @@ return an empty string." (org-element-property :org-marker element)))) (with-current-buffer (marker-buffer marker) (org-with-wide-buffer + (goto-char marker) (cl-loop for type in (org-ql--tags-at marker) unless (or (eq 'org-ql-nil type) (not type)) From bfd4d462a0d755721c7cd5bd6f1516b60387eeb0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 21:17:27 -0600 Subject: [PATCH 174/560] Add/Change/Fix: Storing links to containing buffer or files This feels too complicated, but I don't see a way around it, short of redesigning all of the argument expansion/contraction, which might end up in the same place, anyway. See #147. --- org-ql-view.el | 93 +++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 39 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 087ff77..d569741 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -623,7 +623,7 @@ protocol. See, e.g. `org-ql-view--link-store'." (title (--when-let (alist-get "title" params nil nil #'string=) (read it))) (buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=) - (read it) + (org-ql-view--expand-buffers-files (read it)) (current-buffer)))) (when (and org-ql-view-ask-unsafe-links (or (string-match (rx bol (0+ space) "(") query) @@ -642,39 +642,43 @@ protocol. See, e.g. `org-ql-view--link-store'." :super-groups groups :title title))) +(defvar org-ql-view--link-store-counter 0 + "Workaround for an idiosyncrasy of `org-store-link' that calls link-storing functions twice.") + (defun org-ql-view--link-store () "Store a link to the current Org QL view. When opened, the link searches the buffer it's opened from." (require 'url-parse) (require 'url-util) (when org-ql-view-query - (unless (cl-etypecase org-ql-view-buffers-files - ;; I really wish `anaphora' were in ELPA, because `aetypecase' would be - ;; nice here, and I'd prefer to avoid adding more MELPA-only dependencies. - (buffer t) - (string (file-exists-p org-ql-view-buffers-files)) - (list (and (cl-every #'stringp org-ql-view-buffers-files) - (cl-every #'file-exists-p org-ql-view-buffers-files)))) - (user-error "Can only store links to views of either a single buffer/file or a list of files")) - (let* ((params (list (when (and org-ql-view-buffers-files - ;; If it's one buffer (i.e. the view searches the current - ;; buffer), don't serialize it, because buffers are unreadable. - (not (bufferp org-ql-view-buffers-files))) - (list "buffers-files" (prin1-to-string org-ql-view-buffers-files))) - (when org-ql-view-super-groups - (list "super-groups" (prin1-to-string org-ql-view-super-groups))) - (when org-ql-view-sort - (list "sort" (prin1-to-string org-ql-view-sort))) - (when org-ql-view-title - (list "title" (prin1-to-string org-ql-view-title))))) - (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) - "?" (url-build-query-string (delete nil params)))) - (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil - filename)))) - (org-store-link-props - :type "org-ql-search" - :link url - :description (concat "org-ql-search: " org-ql-view-title))) + (cl-incf org-ql-view--link-store-counter) + ;; Only Org QL View buffers should have `org-ql-view-query' set. + (cl-flet ((prompt-for (buffers-files) + ;; HACK: Use counter to avoid prompting the first of the + ;; two times that `org-store-link' calls this function. + (when (cl-evenp org-ql-view--link-store-counter) + (pcase-exhaustive + (completing-read (format "Link to search file containing inserted link or %s? " buffers-files) + (list "containing file" buffers-files) nil t) + ("containing file" nil) + (buffers-files (prin1-to-string buffers-files)))))) + (let* ((buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) + (params (list (when buffers-files + (list "buffers-files" buffers-files)) + (when org-ql-view-super-groups + (list "super-groups" (prin1-to-string org-ql-view-super-groups))) + (when org-ql-view-sort + (list "sort" (prin1-to-string org-ql-view-sort))) + (when org-ql-view-title + (list "title" (prin1-to-string org-ql-view-title))))) + (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) + "?" (url-build-query-string (delete nil params)))) + (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil + filename)))) + (org-store-link-props + :type "org-ql-search" + :link url + :description (concat "org-ql-search: " org-ql-view-title)))) t)) ;;;; Transient @@ -992,6 +996,9 @@ property." ;;;;; Completion +;; These functions are somewhat regrettable because of the need to keep them +;; in sync, but it seems worth it to provide users with the flexibility. + (defun org-ql-view--contract-buffers-files (buffers-files) "Return BUFFERS-FILES in its \"contracted\" form. The contracted form is \"org-agenda-files\" if BUFFERS-FILES @@ -1020,6 +1027,8 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." "buffer") ((or 'org-agenda-files '(function org-agenda-files)) "org-agenda-files") + ((and (pred bufferp) (guard (file-exists-p (buffer-file-name buffers-files)))) + (buffer-file-name buffers-files)) (_ (let ((print-length nil)) (prin1-to-string buffers-files)))))) @@ -1034,17 +1043,23 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." ;; Buffers can't be input by name, so if the default value is a buffer, just use it. ;; TODO: Find a way to fix this. org-ql-view-buffers-files - (pcase-exhaustive - (completing-read "Buffers/Files: " - (list 'buffer 'org-agenda-files 'org-directory 'all) - nil nil (initial-input)) - ((or "" "buffer") (current-buffer)) - ("org-agenda-files" (org-agenda-files)) - ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) - (buffer-list))) - ("org-directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) - (else (s-split (rx (1+ space)) else)))))) + (org-ql-view--expand-buffers-files + (completing-read "Buffers/Files: " + (list 'buffer 'org-agenda-files 'org-directory 'all) + nil nil (initial-input)))))) + +(defun org-ql-view--expand-buffers-files (buffers-files) + "Return BUFFERS-FILES expanded to a list of files or buffers. +The counterpart to `org-ql-view--contract-buffers-files'." + (pcase-exhaustive buffers-files + ((pred bufferp) buffers-files) + ((or "" "buffer") (current-buffer)) + ("org-agenda-files" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("org-directory" (org-ql-search-directories-files)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else)))) (defun org-ql-view--complete-super-groups () "Return value for `org-ql-view-super-groups' using completion." From 07d21e57c01d66dce085bf62c7d5ced44916168d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Nov 2020 21:21:26 -0600 Subject: [PATCH 175/560] Tidy --- org-ql-view.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index d569741..f6c9917 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -651,8 +651,8 @@ When opened, the link searches the buffer it's opened from." (require 'url-parse) (require 'url-util) (when org-ql-view-query - (cl-incf org-ql-view--link-store-counter) ;; Only Org QL View buffers should have `org-ql-view-query' set. + (cl-incf org-ql-view--link-store-counter) (cl-flet ((prompt-for (buffers-files) ;; HACK: Use counter to avoid prompting the first of the ;; two times that `org-store-link' calls this function. From e15cc3eb764a3d60f475789432379369a1295850 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 02:30:37 -0600 Subject: [PATCH 176/560] Add: (--query-sexp-to-string) --- org-ql.el | 71 ++++ tests/test-org-ql.el | 947 +++++++++++++++++++++++-------------------- 2 files changed, 568 insertions(+), 450 deletions(-) diff --git a/org-ql.el b/org-ql.el index c638f4d..f6639c4 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1668,6 +1668,8 @@ element should be a regexp string." ;; This section implements parsing of "plain," non-Lisp queries using the `peg' ;; library. NOTE: This needs to appear after the predicates are defined. +;; TODO: Rename "plain" to "string", or something like that. + (require 'peg) ;; Fix compiler warnings probably caused by `peg' not using lexical-binding. @@ -1749,6 +1751,75 @@ Multiple predicates are combined with BOOLEAN." (org-ql--def-plain-query-fn)) +;; And now we go the other direction... + +(defun org-ql--query-sexp-to-string (query) + "Return a string query for sexp QUERY. +If QUERY can't be converted to a string, return nil." + ;; This started out pretty simple...but at least it's not just one long function, right? + (cl-labels ((complex-p (query) + (or (contains-p 'or query))) + (contains-p (symbol list) + (cl-loop for element in list + thereis (or (eq symbol element) + (and (listp element) + (contains-p symbol element))))) + (format-args + (args) (let (non-paired paired next-keyword) + (cl-loop for arg in args + do (cond (next-keyword (push (cons next-keyword arg) paired) + (setf next-keyword nil)) + ((keywordp arg) (setf next-keyword (substring (symbol-name arg) 1))) + (t (push arg non-paired)))) + (string-join (append (mapcar #'format-atom non-paired) + (nreverse (--map (format "%s=%s" (car it) (cdr it)) + paired))) + ","))) + (format-atom + (atom) (cl-typecase atom + (string (if (string-match (rx space) atom) + (format "%S" atom) + (format "%s" atom))) + (t (format "%s" atom)))) + (format-form + (form) (pcase form + (`(not . (,rest)) (concat "!" (format-form rest))) + (`(priority . ,_) (format-priority form)) + ;; FIXME: Convert (src) queries to non-sexp form...someday... + (`(src . ,_) (user-error "Converting (src ...) queries to non-sexp form is not implemented")) + (_ (pcase-let* ((`(,pred . ,args) form) + (args-string (pcase args + ('() "") + ((guard (= 1 (length args))) (format "%s" (car args))) + (_ (format-args args))))) + (format "%s:%s" pred args-string))))) + (format-and + (form) (pcase-let* ((`(and . ,rest) form)) + (string-join (mapcar #'format-form rest) " "))) + (format-priority + (form) (pcase-let* ((`(priority . ,rest) form) + (args (pcase rest + (`(,(and comparator (or '< '<= '> '>= '=)) ,letter) + (priority-letters comparator letter)) + (_ rest)))) + (concat "priority:" (string-join args ",")))) + (priority-letters + (comparator letter) (let* ((char (string-to-char (upcase (symbol-name letter)))) + (numeric-priorities '(?A ?B ?C)) + ;; NOTE: The comparator inversion is intentional. + (others (pcase comparator + ('< (--select (> it char) numeric-priorities)) + ('<= (--select (>= it char) numeric-priorities)) + ('> (--select (< it char) numeric-priorities)) + ('>= (--select (<= it char) numeric-priorities)) + ('= (--select (= it char) numeric-priorities))))) + (mapcar #'char-to-string others)))) + ;; FIXME: Error out for ts structs passed to `ts' predicate (very unlikely to be linked to). + (unless (complex-p query) + (pcase query + (`(and . ,_) (format-and query)) + (_ (format-form query)))))) + ;;;; Footer (provide 'org-ql) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index c28d728..93a042d 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -368,345 +368,392 @@ RESULTS should be a list of strings as returned by (expect (org-ql--plain-query "regexp:\"quoted phrase\" todo:SOMEDAY") :to-equal '(and (regexp "quoted phrase") (todo "SOMEDAY"))))) + (describe "Convert sexp queries to non-sexp queries" + + ;; FIXME: Test (src) after converting it is implemented. + ;; (src :lang "elisp" :regexps ("defun")) + + ;; MAYBE: Other predicates? Or should these cover the other + ;; cases, because the others use the same format? + + (it "(heading)" + (expect (org-ql--query-sexp-to-string '(heading "quoted phrase" "word")) + :to-equal "heading:word,\"quoted phrase\"")) + (it "(priority)" + (expect (org-ql--query-sexp-to-string '(priority >= B)) + :to-equal "priority:A,B") + (expect (org-ql--query-sexp-to-string '(priority > B)) + :to-equal "priority:A") + (expect (org-ql--query-sexp-to-string '(priority < B)) + :to-equal "priority:C") + (expect (org-ql--query-sexp-to-string '(priority < A)) + :to-equal "priority:B,C") + (expect (org-ql--query-sexp-to-string '(priority <= B)) + :to-equal "priority:B,C") + (expect (org-ql--query-sexp-to-string '(priority = A)) + :to-equal "priority:A")) + (it "(todo)" + (expect (org-ql--query-sexp-to-string '(todo)) + :to-equal "todo:") + (expect (org-ql--query-sexp-to-string '(todo "TODO")) + :to-equal "todo:TODO") + (expect (org-ql--query-sexp-to-string '(todo "TODO" "NEXT")) + :to-equal "todo:NEXT,TODO")) + (it "(ts)" + (expect (org-ql--query-sexp-to-string '(ts :from -1 :to 1)) + :to-equal "ts:from=-1,to=1") + (expect (org-ql--query-sexp-to-string '(ts :on today)) + :to-equal "ts:on=today") + (expect (org-ql--query-sexp-to-string '(ts-active :from "2017-01-01" :to "2018-01-01")) + :to-equal "ts-active:from=2017-01-01,to=2018-01-01")) + (it "(and ...)" + (expect (org-ql--query-sexp-to-string '(and (tags "book" "books") (priority "A"))) + :to-equal "tags:books,book priority:A") + (expect (org-ql--query-sexp-to-string '(and (tags "space") (not (regexp "moon")))) + :to-equal "tags:space !regexp:moon")) + (it "(or ...)" + (expect (org-ql--query-sexp-to-string '(or (tags "book" "books") (priority "A"))) + :to-equal nil))) + (describe "Query results" ;; TODO: Other predicates. (describe "(ancestors)" (org-ql-it "without sub-query" - (org-ql-expect ((ancestors)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((ancestors)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((ancestors (heading "universe"))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((ancestors (heading "universe"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(parent)" (org-ql-it "without sub-query" - (org-ql-expect ((parent)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((parent)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((parent (and (todo) (priority "A")))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((parent (and (todo) (priority "A")))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(category)" (org-ql-it "without arguments" - (expect (length (org-ql org-ql-test-buffer - (category))) - :to-equal org-ql-test-num-headings)) + (expect (length (org-ql org-ql-test-buffer + (category))) + :to-equal org-ql-test-num-headings)) (org-ql-it "with a category" - (org-ql-expect ((category "ambition")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((category "ambition")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(children)" (org-ql-it "without arguments" - (org-ql-expect ((children)) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) + (org-ql-expect ((children)) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((children (todo "CHECK"))) - '("Recurring"))) + (org-ql-expect ((children (todo "CHECK"))) + '("Recurring"))) (org-ql-it "with grandchildren query" - ;; It's really cool how this works. It's so simple. - (org-ql-expect ((children (children "moon"))) - '("Take over the universe")))) + ;; It's really cool how this works. It's so simple. + (org-ql-expect ((children (children "moon"))) + '("Take over the universe")))) (describe "(descendants)" (org-ql-it "without arguments" - (org-ql-expect ((descendants)) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) + (org-ql-expect ((descendants)) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((descendants (todo "CHECK"))) - '("Recurring"))) + (org-ql-expect ((descendants (todo "CHECK"))) + '("Recurring"))) (org-ql-it "with granddescendants query" - (org-ql-expect ((descendants (descendants "moon"))) - '("Take over the universe"))) + (org-ql-expect ((descendants (descendants "moon"))) + '("Take over the universe"))) (org-ql-it "with query that should not match parent" - ;; This test would fail if the `descendants' predicate did not properly exclude - ;; the parent heading by narrowing the buffer to begin at the first child. - (org-ql-expect ((and (descendants (todo "WAITING")) - (not (descendants (todo "TODO" "NEXT"))))) - '("Take over the moon")))) + ;; This test would fail if the `descendants' predicate did not properly exclude + ;; the parent heading by narrowing the buffer to begin at the first child. + (org-ql-expect ((and (descendants (todo "WAITING")) + (not (descendants (todo "TODO" "NEXT"))))) + '("Take over the moon")))) (describe "(clocked)" (org-ql-it "without arguments" - (org-ql-expect ((clocked)) - '("Learn universal sign language"))) + (org-ql-expect ((clocked)) + '("Learn universal sign language"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((clocked 10)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked 10)) + '("Learn universal sign language")))) (org-ql-it ":from a timestamp" - (org-ql-expect ((clocked :from "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06")) - nil)) + (org-ql-expect ((clocked :from "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :from "2017-07-06")) + nil)) (org-ql-it ":from today" - (org-ql-then - (org-ql-expect ((clocked :from today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :from today)) + '("Learn universal sign language")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((clocked :to "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :to "2017-07-04")) - nil)) + (org-ql-expect ((clocked :to "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :to "2017-07-04")) + nil)) (org-ql-it ":to today" - (org-ql-then - (org-ql-expect ((clocked :to today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :to today)) + '("Learn universal sign language")))) (org-ql-it ":on a date" - (org-ql-expect ((clocked :on "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :on "2018-12-02")) - nil)) + (org-ql-expect ((clocked :on "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :on "2018-12-02")) + nil)) (org-ql-it ":on today" - (org-ql-then - (org-ql-expect ((clocked :on today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :on today)) + '("Learn universal sign language")))) (org-ql-it "within a range (:from and :to)" - (org-ql-expect ((clocked :from "2017-07-04" :to "2018-12-11")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06" :to "2018-12-11")) - nil) - (org-ql-expect ((clocked :from "2017-07-01" :to "2017-07-04")) - nil))) + (org-ql-expect ((clocked :from "2017-07-04" :to "2018-12-11")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :from "2017-07-06" :to "2018-12-11")) + nil) + (org-ql-expect ((clocked :from "2017-07-01" :to "2017-07-04")) + nil))) (describe "(closed)" (org-ql-it "without arguments" - (org-ql-expect ((closed)) - '("Learn universal sign language"))) + (org-ql-expect ((closed)) + '("Learn universal sign language"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((closed 10)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((closed 10)) + '("Learn universal sign language")))) (org-ql-it ":on" - (org-ql-expect ((closed :on "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :on today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :on "2019-06-09")) - nil)) + (org-ql-expect ((closed :on "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :on today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :on "2019-06-09")) + nil)) (org-ql-it ":from" - (org-ql-expect ((closed :from "2017-07-04")) - '("Learn universal sign language")) - (org-ql-expect ((closed :from "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :from today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :from "2017-07-06")) - nil)) + (org-ql-expect ((closed :from "2017-07-04")) + '("Learn universal sign language")) + (org-ql-expect ((closed :from "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :from today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :from "2017-07-06")) + nil)) (org-ql-it ":to" - (org-ql-expect ((closed :to "2017-07-04")) - nil) - (org-ql-expect ((closed :to "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :to today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :to "2017-07-06")) - '("Learn universal sign language")))) + (org-ql-expect ((closed :to "2017-07-04")) + nil) + (org-ql-expect ((closed :to "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :to today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :to "2017-07-06")) + '("Learn universal sign language")))) (describe "(deadline)" (org-ql-it "without arguments" - (org-ql-expect ((deadline)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) + (org-ql-expect ((deadline)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) (org-ql-it "auto" - (org-ql-then - (org-ql-expect ((deadline auto)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + (org-ql-then + (org-ql-expect ((deadline auto)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((deadline 2)) - '("Take over the world" "/r/emacs")))) + (org-ql-then + (org-ql-expect ((deadline 2)) + '("Take over the world" "/r/emacs")))) (org-ql-it ":on" - (org-ql-expect ((deadline :on "2017-07-05")) - '("/r/emacs")) - (org-ql-then - (org-ql-expect ((deadline :on today)) - '("/r/emacs"))) + (org-ql-expect ((deadline :on "2017-07-05")) + '("/r/emacs")) + (org-ql-then + (org-ql-expect ((deadline :on today)) + '("/r/emacs"))) - (org-ql-expect ((deadline :on "2019-06-09")) - nil)) + (org-ql-expect ((deadline :on "2019-06-09")) + nil)) (org-ql-it ":from" - (org-ql-expect ((deadline :from "2017-07-04")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((deadline :from "2018-07-06")) - nil) - (org-ql-then - (org-ql-expect ((deadline :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + (org-ql-expect ((deadline :from "2017-07-04")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-expect ((deadline :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-expect ((deadline :from "2017-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-expect ((deadline :from "2018-07-06")) + nil) + (org-ql-then + (org-ql-expect ((deadline :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it ":to" - (org-ql-expect ((deadline :to "2017-07-04")) - nil) - (org-ql-expect ((deadline :to "2017-07-05")) - '("/r/emacs")) - (org-ql-expect ((deadline :to "2018-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-then - (org-ql-expect ((deadline :to today)) - '("/r/emacs"))))) + (org-ql-expect ((deadline :to "2017-07-04")) + nil) + (org-ql-expect ((deadline :to "2017-07-05")) + '("/r/emacs")) + (org-ql-expect ((deadline :to "2018-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-then + (org-ql-expect ((deadline :to today)) + '("/r/emacs"))))) (org-ql-it "(done)" - (org-ql-expect ((done)) - '("Learn universal sign language"))) + (org-ql-expect ((done)) + '("Learn universal sign language"))) (org-ql-it "(habit)" - (org-ql-expect ((habit)) - '("Practice leaping tall buildings in a single bound"))) + (org-ql-expect ((habit)) + '("Practice leaping tall buildings in a single bound"))) (describe "(heading)" (org-ql-it "with one argument" - (org-ql-expect ((heading "world")) - ;; NOTE: This--correctly--does not match the "Skype with president of - ;; Antarctica" heading, which has the tag ":world:" in its heading line. - '("Take over the world"))) + (org-ql-expect ((heading "world")) + ;; NOTE: This--correctly--does not match the "Skype with president of + ;; Antarctica" heading, which has the tag ":world:" in its heading line. + '("Take over the world"))) (org-ql-it "with two arguments" - (org-ql-expect ((heading "Take over" "world")) - '("Take over the world")))) + (org-ql-expect ((heading "Take over" "world")) + '("Take over the world")))) (describe "(link)" (org-ql-it "without arguments" - (org-ql-expect ((link)) - '("/r/emacs"))) + (org-ql-expect ((link)) + '("/r/emacs"))) (org-ql-it "with description-or-target" - (org-ql-expect ((link "emacs")) - '("/r/emacs"))) + (org-ql-expect ((link "emacs")) + '("/r/emacs"))) (org-ql-it "with :description" - (org-ql-expect ((link :description "emacs")) - '("/r/emacs"))) + (org-ql-expect ((link :description "emacs")) + '("/r/emacs"))) (org-ql-it "with :target" - (org-ql-expect ((link :target "reddit.com")) - '("/r/emacs"))) + (org-ql-expect ((link :target "reddit.com")) + '("/r/emacs"))) (org-ql-it "with :description and :target" - (org-ql-expect ((link :description "emacs" :target "reddit.com")) - '("/r/emacs")))) + (org-ql-expect ((link :description "emacs" :target "reddit.com")) + '("/r/emacs")))) (describe "(outline-path)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path "symphony")) + '("Write a symphony"))) (org-ql-it "with two arguments" - (org-ql-expect ((outline-path "idea" "symphony")) - '("Write a symphony")))) + (org-ql-expect ((outline-path "idea" "symphony")) + '("Write a symphony")))) (describe "(outline-path-segment)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path-segment "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path-segment "symphony")) + '("Write a symphony"))) (org-ql-it "with a contiguous segment" - (org-ql-expect ((outline-path-segment "idea" "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path-segment "idea" "symphony")) + '("Write a symphony"))) (org-ql-it "with a non-contiguous segment" - (org-ql-expect ((outline-path-segment "data" "symphony")) - nil))) + (org-ql-expect ((outline-path-segment "data" "symphony")) + nil))) (describe "(path)" (org-ql-it "without arguments" - (org-ql-expect ((path)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with one argument" - (org-ql-expect ((path "data")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path "data")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two matching arguments" - (org-ql-expect ((path "data" "tests")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path "data" "tests")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two arguments, one matching" - (org-ql-expect ((path "data" "nope")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (org-ql-expect ((path "data" "nope")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(planning)" (org-ql-it "without arguments" - (org-ql-expect ((planning)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((planning)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((planning 2)) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((planning 2)) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on" - (org-ql-expect ((planning :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :on "2019-06-09")) - nil) - (org-ql-then - (org-ql-expect ((planning :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((planning :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :on "2019-06-09")) + nil) + (org-ql-then + (org-ql-expect ((planning :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((planning :from "2017-07-04")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-then - (org-ql-expect ((planning :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((planning :from "2017-07-04")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :from "2017-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-then + (org-ql-expect ((planning :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((planning :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((planning :to "2017-07-05")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :to "2018-07-06")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-then - (org-ql-expect ((planning :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) + (org-ql-expect ((planning :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((planning :to "2017-07-05")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :to "2018-07-06")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-then + (org-ql-expect ((planning :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) (describe "(priority)" (org-ql-it "without arguments" - (org-ql-expect ((priority)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor"))) + (org-ql-expect ((priority)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor"))) (org-ql-it "with a priority" - (org-ql-expect ((priority "A")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority "A")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "= a priority" - (org-ql-expect ((priority = "A")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority = "A")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "< a priority" - (org-ql-expect ((priority < "B")) - '("Take over the moon" "Get haircut"))) + (org-ql-expect ((priority < "B")) + '("Take over the moon" "Get haircut"))) (org-ql-it "<= a priority" - (org-ql-expect ((priority <= "B")) - '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor"))) + (org-ql-expect ((priority <= "B")) + '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor"))) (org-ql-it "> a priority" - (org-ql-expect ((priority > "B")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority > "B")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it ">= a priority" - (org-ql-expect ((priority >= "B")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))) + (org-ql-expect ((priority >= "B")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))) (describe "(property)" ;; MAYBE: Add support for (property) without arguments. @@ -714,84 +761,84 @@ RESULTS should be a list of strings as returned by ;; (org-ql-expect ((property)))) (org-ql-it "with a property" - (org-ql-expect ((property "agenda-group")) - '("Take over the universe" "Spaceship lease" "Recurring" "Write a symphony"))) + (org-ql-expect ((property "agenda-group")) + '("Take over the universe" "Spaceship lease" "Recurring" "Write a symphony"))) (org-ql-it "with a property and a value" - (org-ql-expect ((property "agenda-group" "plans")) - '("Take over the universe" "Write a symphony")))) + (org-ql-expect ((property "agenda-group" "plans")) + '("Take over the universe" "Write a symphony")))) (describe "(regexp)" (org-ql-it "with 1 argument" - (org-ql-expect ((regexp "Take over") - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ((regexp "Take over") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((regexp "Take over" "universe") - :sort todo) - '("Take over the universe"))) + (org-ql-expect ((regexp "Take over" "universe") + :sort todo) + '("Take over the universe"))) (org-ql-it "with a plain string" - (org-ql-expect ("Take over" - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ("Take over" + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with two plain strings in an OR" - (org-ql-expect ((or "Take over" "universe") - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ((or "Take over" "universe") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "case-folding predicate with non-case-folding preamble" - ;; e.g. the (todo) predicate disables case-folding in its preamble, but that - ;; should not prevent case-folding in this and other predicates (issue #114). - (org-ql-expect ((and (todo "TODO") (regexp "take over")) - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) + ;; e.g. the (todo) predicate disables case-folding in its preamble, but that + ;; should not prevent case-folding in this and other predicates (issue #114). + (org-ql-expect ((and (todo "TODO") (regexp "take over")) + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) (describe "(scheduled)" (org-ql-it "without arguments" - (org-ql-expect ((scheduled)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((scheduled)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" - (org-ql-then - ;; Using -1 is the easiest way to exclude some results but not all for testing this. - (org-ql-expect ((scheduled -1)) - '("Skype with president of Antarctica")))) + (org-ql-then + ;; Using -1 is the easiest way to exclude some results but not all for testing this. + (org-ql-expect ((scheduled -1)) + '("Skype with president of Antarctica")))) (org-ql-it ":on" - (org-ql-expect ((scheduled :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :on "2019-06-09")) - nil) - (org-ql-then - (org-ql-expect ((scheduled :on today)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((scheduled :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :on "2019-06-09")) + nil) + (org-ql-then + (org-ql-expect ((scheduled :on today)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((scheduled :from "2017-07-04")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-06")) - nil) - (org-ql-then - (org-ql-expect ((scheduled :from today)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((scheduled :from "2017-07-04")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :from "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :from "2017-07-06")) + nil) + (org-ql-then + (org-ql-expect ((scheduled :from today)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((scheduled :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((scheduled :to "2017-07-05")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :to "2018-07-06")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-then - (org-ql-expect ((scheduled :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) + (org-ql-expect ((scheduled :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((scheduled :to "2017-07-05")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :to "2018-07-06")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-then + (org-ql-expect ((scheduled :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) ;; TODO: Test (src) predicate. That will require modifying test data, which will be a ;; significant hassle. Manual testing shows that the predicate appears to work properly. @@ -799,288 +846,288 @@ RESULTS should be a list of strings as returned by (describe "(todo)" (org-ql-it "without arguments" - (org-ql-expect ((todo) - :sort todo) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((todo) + :sort todo) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 1 argument" - (org-ql-expect ((todo "WAITING") - :sort todo) - '("Visit the moon"))) + (org-ql-expect ((todo "WAITING") + :sort todo) + '("Visit the moon"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((todo "WAITING" "SOMEDAY") - :sort todo) - '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (org-ql-expect ((todo "WAITING" "SOMEDAY") + :sort todo) + '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(tags)" (org-ql-it "without arguments" - (org-ql-expect ((tags)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (tags))) - '("Recurring" "Sunrise/sunset" "Ideas"))) + (org-ql-expect ((tags)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) + (org-ql-expect ((not (tags))) + '("Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags "Emacs")) - '("/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs"))) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + (org-ql-expect ((tags "Emacs")) + '("/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags "Emacs"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((tags "Emacs" "space")) - '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs" "space"))) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + (org-ql-expect ((tags "Emacs" "space")) + '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags "Emacs" "space"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags "food")) - '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags "fruit")) - '("Fruit" "Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-inherited)" (org-ql-it "without arguments" - (org-ql-expect ((tags-inherited)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (inherited-tags))) - '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-inherited)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) + (org-ql-expect ((not (inherited-tags))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-inherited "Emacs")) - nil) - (org-ql-expect ((itags "ambition")) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (tags-i "ambition"))) - '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-inherited "Emacs")) + nil) + (org-ql-expect ((itags "ambition")) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) + (org-ql-expect ((not (tags-i "ambition"))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((itags "personal" "world")) - '("Skype with president of Antarctica")) - (org-ql-expect ((not (tags-inherited "personal" "world"))) - ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". - '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((itags "personal" "world")) + '("Skype with president of Antarctica")) + (org-ql-expect ((not (tags-inherited "personal" "world"))) + ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". + '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-inherited "food")) - '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-inherited "fruit")) - '("Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-inherited "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-inherited "fruit")) + '("Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-local)" (org-ql-it "without arguments" - (org-ql-expect ((tags-local)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (local-tags))) - '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) + (org-ql-expect ((tags-local)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) + (org-ql-expect ((not (local-tags))) + '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-local "world")) - '("Take over the world" "Skype with president of Antarctica")) - (org-ql-expect ((ltags "ambition")) - '("Take over the universe")) - (org-ql-expect ((not (tags-l "ambition"))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-local "world")) + '("Take over the world" "Skype with president of Antarctica")) + (org-ql-expect ((ltags "ambition")) + '("Take over the universe")) + (org-ql-expect ((not (tags-l "ambition"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((ltags "personal" "world")) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) - (org-ql-expect ((not (tags-local "personal" "world"))) - '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((ltags "personal" "world")) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) + (org-ql-expect ((not (tags-local "personal" "world"))) + '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-local "food")) - nil - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-local "fruit")) - '("Fruit") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-local "food")) + nil + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-local "fruit")) + '("Fruit") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-all), (tags&)" (org-ql-it "with 2 tags" - (org-ql-expect ((tags-all "universe" "personal")) - '("Practice leaping tall buildings in a single bound")) - (org-ql-expect ((tags& "ambition" "space")) - '("Visit Mars" "Visit the moon"))) + (org-ql-expect ((tags-all "universe" "personal")) + '("Practice leaping tall buildings in a single bound")) + (org-ql-expect ((tags& "ambition" "space")) + '("Visit Mars" "Visit the moon"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-all "food" "fruit")) - '("Fruit" "Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-all "food" "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(ts)" (describe "active" (org-ql-it "without arguments" - (org-ql-expect ((ts :type active)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts :type active)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-08" :type active)) - '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((ts :from "2019-06-08" :type active)) - nil) - (org-ql-then - (org-ql-expect ((ts :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-08" :type active)) + '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-expect ((ts :from "2019-06-08" :type active)) + nil) + (org-ql-then + (org-ql-expect ((ts :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts :from 5)) - '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :from 5)) + '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type active)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type active)) - '("Skype with president of Antarctica")) - (org-ql-then - (org-ql-expect ((ts :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :to "2019-06-10" :type active)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04" :type active)) + '("Skype with president of Antarctica")) + (org-ql-then + (org-ql-expect ((ts :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts :to -1)) - '("Skype with president of Antarctica")))) + (org-ql-then + (org-ql-expect ((ts :to -1)) + '("Skype with president of Antarctica")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type active)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09" :type active)) - nil) - (org-ql-then - (org-ql-expect ((ts :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :on "2017-07-05" :type active)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2019-06-09" :type active)) + nil) + (org-ql-then + (org-ql-expect ((ts :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts-active :on 2)) - '("Take over the world"))))) + (org-ql-then + (org-ql-expect ((ts-active :on 2)) + '("Take over the world"))))) (describe "inactive" (org-ql-it "without arguments" - (org-ql-expect ((ts :type inactive)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts :type inactive)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-06" :type inactive)) - '("Visit the moon" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08" :type inactive)) - nil) - (org-ql-then - (org-ql-expect ((ts-inactive :from today)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-06" :type inactive)) + '("Visit the moon" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2019-06-08" :type inactive)) + nil) + (org-ql-then + (org-ql-expect ((ts-inactive :from today)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts-i :from 5)) - '("Visit the moon" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts-i :from 5)) + '("Visit the moon" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type inactive)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type inactive)) - 'nil) - (org-ql-then - (org-ql-expect ((ts-inactive :to today)) - '("Learn universal sign language")))) + (org-ql-expect ((ts :to "2019-06-10" :type inactive)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04" :type inactive)) + 'nil) + (org-ql-then + (org-ql-expect ((ts-inactive :to today)) + '("Learn universal sign language")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts-i :to 5)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((ts-i :to 5)) + '("Learn universal sign language")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type inactive)) - '("Learn universal sign language")) - (org-ql-expect ((ts :on "2019-06-09" :type inactive)) - nil) - (org-ql-then - (org-ql-expect ((ts-inactive :on today)) - '("Learn universal sign language")))) + (org-ql-expect ((ts :on "2017-07-05" :type inactive)) + '("Learn universal sign language")) + (org-ql-expect ((ts :on "2019-06-09" :type inactive)) + nil) + (org-ql-then + (org-ql-expect ((ts-inactive :on today)) + '("Learn universal sign language")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts-inactive :on 19)) - '("Visit the moon" "Rewrite Emacs in Common Lisp"))))) + (org-ql-then + (org-ql-expect ((ts-inactive :on 19)) + '("Visit the moon" "Rewrite Emacs in Common Lisp"))))) (describe "both" (org-ql-it "without arguments" - (org-ql-expect ((ts)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :type both)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :type both)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2017-07-05" :type both)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08")) - nil) - (org-ql-expect ((ts :from "2019-06-08" :type both)) - nil) - (org-ql-then - (org-ql-expect ((ts :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2017-07-05" :type both)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2019-06-08")) + nil) + (org-ql-expect ((ts :from "2019-06-08" :type both)) + nil) + (org-ql-then + (org-ql-expect ((ts :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts :from -5)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :from -5)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2017-07-06")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-06" :type both)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((ts :to "2017-07-04" :type both)) - '("Skype with president of Antarctica")) - (org-ql-then - (org-ql-expect ((ts :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :to "2017-07-06")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-06" :type both)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((ts :to "2017-07-04" :type both)) + '("Skype with president of Antarctica")) + (org-ql-then + (org-ql-expect ((ts :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts :to 5)) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :to 5)) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2017-07-05" :type both)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09")) - nil) - (org-ql-expect ((ts :on "2019-06-09" :type both)) - nil) - (org-ql-then - (org-ql-expect ((ts :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2017-07-05" :type both)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2019-06-09")) + nil) + (org-ql-expect ((ts :on "2019-06-09" :type both)) + nil) + (org-ql-then + (org-ql-expect ((ts :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts :on 5)) - '("Renew membership in supervillain club")))))) + (org-ql-then + (org-ql-expect ((ts :on 5)) + '("Renew membership in supervillain club")))))) (describe "Compound queries" (org-ql-it "Tags and to-do" - (org-ql-expect ((and (todo "SOMEDAY") - (tags "Emacs"))) - '("Rewrite Emacs in Common Lisp")))))) + (org-ql-expect ((and (todo "SOMEDAY") + (tags "Emacs"))) + '("Rewrite Emacs in Common Lisp")))))) ;; Local Variables: ;; truncate-lines: t From ef40a25b05c95478d3377d9f57c09e3bc7df6e34 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 02:38:30 -0600 Subject: [PATCH 177/560] Change: (org-ql-view--link-store) Convert queries to strings See #147. --- org-ql-view.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index f6c9917..8f1b50d 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -662,7 +662,9 @@ When opened, the link searches the buffer it's opened from." (list "containing file" buffers-files) nil t) ("containing file" nil) (buffers-files (prin1-to-string buffers-files)))))) - (let* ((buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) + (let* ((query-string (--if-let (org-ql--query-sexp-to-string org-ql-view-query) + it (prin1-to-string (org-ql-view--format-query org-ql-view-query)))) + (buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) (params (list (when buffers-files (list "buffers-files" buffers-files)) (when org-ql-view-super-groups @@ -671,7 +673,7 @@ When opened, the link searches the buffer it's opened from." (list "sort" (prin1-to-string org-ql-view-sort))) (when org-ql-view-title (list "title" (prin1-to-string org-ql-view-title))))) - (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) + (filename (concat (url-hexify-string query-string) "?" (url-build-query-string (delete nil params)))) (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil filename)))) From 01660aac22f2a4192ad9380015b4fa0bed5296b8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 02:42:32 -0600 Subject: [PATCH 178/560] Notes: Update --- notes.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notes.org b/notes.org index d7ff1d5..0d9c408 100644 --- a/notes.org +++ b/notes.org @@ -321,6 +321,8 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test [2020-11-11 Wed 01:45] Seems to work well. Now to integrate that into link-saving... +[2020-11-11 Wed 02:41] Seems to work. Will [[https://github.com/alphapapa/org-ql/issues/147#issuecomment-725287074][wait for feedback]] before merging. + ** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] + Added example to =examples.org=. From 87b952c7bf8f947997006651dd08818824e5ad85 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:05:38 -0600 Subject: [PATCH 179/560] Fix: (org-ql-view--link-store) Don't store link to buffers --- org-ql-view.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index 8f1b50d..0bb873a 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -652,6 +652,10 @@ When opened, the link searches the buffer it's opened from." (require 'url-util) (when org-ql-view-query ;; Only Org QL View buffers should have `org-ql-view-query' set. + (when (or (bufferp org-ql-view-buffers-files) + (cl-some #'bufferp org-ql-view-buffers-files)) + ;; Buffers are unreadable, so they can't be linked to. + (user-error "Views that search buffers rather than files can't be linked to")) (cl-incf org-ql-view--link-store-counter) (cl-flet ((prompt-for (buffers-files) ;; HACK: Use counter to avoid prompting the first of the From 33df77420eab1e473ddd4868ca10fac9ad439bb7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:25:54 -0600 Subject: [PATCH 180/560] Notes: Update --- notes.org | 518 +++++++++++++++++++++++++++--------------------------- 1 file changed, 262 insertions(+), 256 deletions(-) diff --git a/notes.org b/notes.org index 0d9c408..3e9aea5 100644 --- a/notes.org +++ b/notes.org @@ -227,262 +227,6 @@ See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test ** TODO [#C] Update commentary -** UNDERWAY [#A] Convert simple sexp queries to non-sexp - -[2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... - -#+BEGIN_SRC elisp - (defun org-ql--query-sexp-to-plain (query) - "Return a plain query string for sexp QUERY. - If QUERY can't be converted to a plain one, return nil." - ;; This started out pretty simple...but at least it's not just one long function, right? - (cl-labels ((complex-p (query) - (or (contains-p 'or query))) - (contains-p (symbol list) - (cl-loop for element in list - thereis (or (eq symbol element) - (and (listp element) - (contains-p symbol element))))) - (format-args - (args) (let (non-paired paired next-keyword) - (cl-loop for arg in args - do (cond (next-keyword (push (cons next-keyword arg) paired) - (setf next-keyword nil)) - ((keywordp arg) (setf next-keyword (substring (symbol-name arg) 1))) - (t (push arg non-paired)))) - (string-join (append (mapcar #'format-atom non-paired) - (nreverse (--map (format "%s=%s" (car it) (cdr it)) - paired))) - ","))) - (format-atom - (atom) (cl-typecase atom - (string (if (string-match (rx space) atom) - (format "%S" atom) - (format "%s" atom))) - (t (format "%s" atom)))) - (format-form - (form) (pcase form - (`(not . (,rest)) (concat "!" (format-form rest))) - (`(priority . ,_) (format-priority form)) - ;; FIXME: Convert (src) queries to non-sexp form...someday... - (`(src . ,_) (user-error "Converting (src ...) queries to non-sexp form is not implemented")) - (_ (pcase-let* ((`(,pred . ,args) form) - (args-string (pcase args - ('() "") - ((guard (= 1 (length args))) (format "%s" (car args))) - (_ (format-args args))))) - (format "%s:%s" pred args-string))))) - (format-and - (form) (pcase-let* ((`(and . ,rest) form)) - (string-join (mapcar #'format-form rest) " "))) - (format-priority - (form) (pcase-let* ((`(priority . ,rest) form) - (args (pcase rest - (`(,(and comparator (or < <= > >= =)) ,letter) - (priority-letters comparator letter)) - (_ rest)))) - (concat "priority:" (string-join args ",")))) - (priority-letters - (comparator letter) (let* ((char (string-to-char (upcase (symbol-name letter)))) - (numeric-priorities '(?A ?B ?C)) - ;; NOTE: The comparator inversion is intentional. - (others (pcase comparator - ('< (--select (> it char) numeric-priorities)) - ('<= (--select (>= it char) numeric-priorities)) - ('> (--select (< it char) numeric-priorities)) - ('>= (--select (<= it char) numeric-priorities)) - ('= (--select (= it char) numeric-priorities))))) - (mapcar #'char-to-string others)))) - (unless (complex-p query) - (pcase query - (`(and . ,_) (format-and query)) - (_ (format-form query)))))) - - (--map (cons it (org-ql--query-sexp-to-plain it)) - '((priority >= B) - (priority > B) - (priority < B) - (priority < A) - (priority = A) - (todo) - (todo "TODO") - (todo "TODO" "NEXT") - (ts :from -1 :to 1) - (ts :on today) - (ts-active :from "2017-01-01" :to "2018-01-01") - (heading "quoted phrase" "word") - (and (tags "book" "books") (priority "A")) - (and (tags "space") (not (regexp "moon"))) - (src :lang "elisp" :regexps ("defun"))) - - - ) -#+END_SRC - -[2020-11-11 Wed 01:45] Seems to work well. Now to integrate that into link-saving... - -[2020-11-11 Wed 02:41] Seems to work. Will [[https://github.com/alphapapa/org-ql/issues/147#issuecomment-725287074][wait for feedback]] before merging. - -** UNDERWAY [#A] Tools for saving queries and accessing them [3/4] - -+ Added example to =examples.org=. - -*** UNDERWAY [#A] Org link types [2/3] -:PROPERTIES: -:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e -:END: - -This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. - -**** TODO For saved queries - -**** DONE For searches - -[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: - -#+BEGIN_SRC org - [[org-ql-search:property:author="AUTHOR"]] -#+END_SRC - -[2020-11-08 Sun 23:22] Seems to work! - -#+BEGIN_SRC elisp :results silent - ;;;; Org link type - - ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. - - (org-link-set-parameters "org-ql-search" - :follow #'org-ql-search--link-open - :store #'org-ql-search--link-store) - - (defun org-ql-search--link-open (query) - "Open Org QL QUERY for current buffer." - (org-ql-search (current-buffer) query)) - - (defun org-ql-search--link-store () - "Store a link to current Org QL query." - ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. - (when org-ql-view-query - (org-store-link-props :type "org-ql-search" - :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) - :description org-ql-view-title) - t)) -#+END_SRC - -Tested on these queries: - -#+BEGIN_SRC org - + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] - + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] - + [[org-ql-search:link:nullprogram]] -#+END_SRC - -[2020-11-10 Tue 00:35] I'd like to support other parameters to the search, like grouping and sorting, so: - -#+BEGIN_SRC elisp :results silent - ;;;; Org link type - - ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. - - (org-link-set-parameters "org-ql-search" - :follow #'org-ql-search--link-open - :store #'org-ql-search--link-store) - - (defun org-ql-search--link-open (query) - "Open Org QL QUERY for current buffer." - (require 'url-parse) - (pcase-let* ((`(,query . ,params) - (url-path-and-query (url-parse-make-urlobj "org-ql-search" nil nil nil nil - query))) - (params (url-parse-query-string params)) - ;; Hacky or elegant? - (_ (mapc (lambda (pair) - (cl-callf (lambda (it) - (intern (concat ":" it))) - (car pair)) - (cl-callf read (cdr pair))) - params)) - (params (cl-loop for (key . value) in params - append (list key value)))) - (apply #'org-ql-search (current-buffer) query params))) - - (defun org-ql-search--link-store () - "Store a link to current Org QL query." - (when org-ql-view-query - (org-store-link-props :type "org-ql-search" - :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) - :description org-ql-view-title) - t)) -#+END_SRC - -That seems to work, like: - -#+BEGIN_SRC org - [[org-ql-search:property:author="Chris%20Wellons"?super-groups=((:auto-outline-path%20t))]] -#+END_SRC - -[2020-11-10 Tue 01:34] Okay, this seems to take care of all parameters: - -#+BEGIN_SRC elisp - (defun org-ql-search--link-open (path) - "Open Org QL query for current buffer at PATH. - PATH should be the part of an \"org-ql-search:\" URL after the - protocol. See, e.g. `org-ql-search--link-store'." - (require 'url-parse) - (require 'url-util) - (pcase-let* ((`(,query . ,params) (url-path-and-query - (url-parse-make-urlobj "org-ql-search" nil nil nil nil - path))) - (query (url-unhex-string query)) - (params (when params - (url-parse-query-string params))) - ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. - (sort (when (alist-get "sort" params nil nil #'string=) - (read (alist-get "sort" params nil nil #'string=)))) - (groups (when (alist-get "super-groups" params nil nil #'string=) - (read (alist-get "super-groups" params nil nil #'string=)))) - (title (when (alist-get "title" params nil nil #'string=) - (read (alist-get "title" params nil nil #'string=))))) - (org-ql-search (current-buffer) query - :sort sort - :super-groups groups - :title title))) - - (defun org-ql-search--link-store () - "Store a link to the current Org QL view. - Only views that search a single buffer may be linked to." - (require 'url-parse) - (require 'url-util) - (unless (or (bufferp org-ql-view-buffers-files) (= 1 (length org-ql-view-buffers-files))) - (user-error "Only views searching a single buffer may be linked")) - (when org-ql-view-query - (let* ((params (list (when org-ql-view-super-groups - (list "super-groups" (prin1-to-string org-ql-view-super-groups))) - (when org-ql-view-sort - (list "sort" (prin1-to-string org-ql-view-sort))) - (when org-ql-view-title - (list "title" (prin1-to-string org-ql-view-title))))) - (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) - "?" (url-build-query-string (delete nil params)))) - (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil - filename)))) - (org-store-link-props - :type "org-ql-search" - :link url - :description (concat "org-ql-search: " org-ql-view-title))) - t)) -#+END_SRC - -**** DONE For all parameters - -*** DONE Bookmarks - -[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. - -*** DONE Access saved query from saved query list - -*** DONE Save query from ql-agenda buffer - ** UNDERWAY [#A] Outline path predicate [2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: @@ -909,6 +653,268 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** PROJECT [#A] Convert simple sexp queries to non-sexp + +[2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... + +#+BEGIN_SRC elisp + (defun org-ql--query-sexp-to-plain (query) + "Return a plain query string for sexp QUERY. + If QUERY can't be converted to a plain one, return nil." + ;; This started out pretty simple...but at least it's not just one long function, right? + (cl-labels ((complex-p (query) + (or (contains-p 'or query))) + (contains-p (symbol list) + (cl-loop for element in list + thereis (or (eq symbol element) + (and (listp element) + (contains-p symbol element))))) + (format-args + (args) (let (non-paired paired next-keyword) + (cl-loop for arg in args + do (cond (next-keyword (push (cons next-keyword arg) paired) + (setf next-keyword nil)) + ((keywordp arg) (setf next-keyword (substring (symbol-name arg) 1))) + (t (push arg non-paired)))) + (string-join (append (mapcar #'format-atom non-paired) + (nreverse (--map (format "%s=%s" (car it) (cdr it)) + paired))) + ","))) + (format-atom + (atom) (cl-typecase atom + (string (if (string-match (rx space) atom) + (format "%S" atom) + (format "%s" atom))) + (t (format "%s" atom)))) + (format-form + (form) (pcase form + (`(not . (,rest)) (concat "!" (format-form rest))) + (`(priority . ,_) (format-priority form)) + ;; FIXME: Convert (src) queries to non-sexp form...someday... + (`(src . ,_) (user-error "Converting (src ...) queries to non-sexp form is not implemented")) + (_ (pcase-let* ((`(,pred . ,args) form) + (args-string (pcase args + ('() "") + ((guard (= 1 (length args))) (format "%s" (car args))) + (_ (format-args args))))) + (format "%s:%s" pred args-string))))) + (format-and + (form) (pcase-let* ((`(and . ,rest) form)) + (string-join (mapcar #'format-form rest) " "))) + (format-priority + (form) (pcase-let* ((`(priority . ,rest) form) + (args (pcase rest + (`(,(and comparator (or < <= > >= =)) ,letter) + (priority-letters comparator letter)) + (_ rest)))) + (concat "priority:" (string-join args ",")))) + (priority-letters + (comparator letter) (let* ((char (string-to-char (upcase (symbol-name letter)))) + (numeric-priorities '(?A ?B ?C)) + ;; NOTE: The comparator inversion is intentional. + (others (pcase comparator + ('< (--select (> it char) numeric-priorities)) + ('<= (--select (>= it char) numeric-priorities)) + ('> (--select (< it char) numeric-priorities)) + ('>= (--select (<= it char) numeric-priorities)) + ('= (--select (= it char) numeric-priorities))))) + (mapcar #'char-to-string others)))) + (unless (complex-p query) + (pcase query + (`(and . ,_) (format-and query)) + (_ (format-form query)))))) + + (--map (cons it (org-ql--query-sexp-to-plain it)) + '((priority >= B) + (priority > B) + (priority < B) + (priority < A) + (priority = A) + (todo) + (todo "TODO") + (todo "TODO" "NEXT") + (ts :from -1 :to 1) + (ts :on today) + (ts-active :from "2017-01-01" :to "2018-01-01") + (heading "quoted phrase" "word") + (and (tags "book" "books") (priority "A")) + (and (tags "space") (not (regexp "moon"))) + (src :lang "elisp" :regexps ("defun"))) + + + ) +#+END_SRC + +[2020-11-11 Wed 01:45] Seems to work well. Now to integrate that into link-saving... + +[2020-11-11 Wed 02:41] Seems to work. Will [[https://github.com/alphapapa/org-ql/issues/147#issuecomment-725287074][wait for feedback]] before merging. + +[2020-11-11 Wed 19:13] Seems to be working properly. One more thing to do though, I think: + +*** TODO [#B] Use string queries in view headers when possible + +Maybe make it an option to automatically convert them when possible, because if a user wanted to add complexity to a string query, he'd have to rewrite it as a sexp. + +** PROJECT [#A] Tools for saving queries and accessing them [3/4] + ++ Added example to =examples.org=. + +*** PROJECT [#A] Org link types [2/3] +:PROPERTIES: +:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e +:END: + +This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. + +**** TODO For saved queries + +**** DONE For searches + +[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: + +#+BEGIN_SRC org + [[org-ql-search:property:author="AUTHOR"]] +#+END_SRC + +[2020-11-08 Sun 23:22] Seems to work! + +#+BEGIN_SRC elisp :results silent + ;;;; Org link type + + ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. + + (org-link-set-parameters "org-ql-search" + :follow #'org-ql-search--link-open + :store #'org-ql-search--link-store) + + (defun org-ql-search--link-open (query) + "Open Org QL QUERY for current buffer." + (org-ql-search (current-buffer) query)) + + (defun org-ql-search--link-store () + "Store a link to current Org QL query." + ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. + (when org-ql-view-query + (org-store-link-props :type "org-ql-search" + :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) + :description org-ql-view-title) + t)) +#+END_SRC + +Tested on these queries: + +#+BEGIN_SRC org + + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] + + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] + + [[org-ql-search:link:nullprogram]] +#+END_SRC + +[2020-11-10 Tue 00:35] I'd like to support other parameters to the search, like grouping and sorting, so: + +#+BEGIN_SRC elisp :results silent + ;;;; Org link type + + ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. + + (org-link-set-parameters "org-ql-search" + :follow #'org-ql-search--link-open + :store #'org-ql-search--link-store) + + (defun org-ql-search--link-open (query) + "Open Org QL QUERY for current buffer." + (require 'url-parse) + (pcase-let* ((`(,query . ,params) + (url-path-and-query (url-parse-make-urlobj "org-ql-search" nil nil nil nil + query))) + (params (url-parse-query-string params)) + ;; Hacky or elegant? + (_ (mapc (lambda (pair) + (cl-callf (lambda (it) + (intern (concat ":" it))) + (car pair)) + (cl-callf read (cdr pair))) + params)) + (params (cl-loop for (key . value) in params + append (list key value)))) + (apply #'org-ql-search (current-buffer) query params))) + + (defun org-ql-search--link-store () + "Store a link to current Org QL query." + (when org-ql-view-query + (org-store-link-props :type "org-ql-search" + :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) + :description org-ql-view-title) + t)) +#+END_SRC + +That seems to work, like: + +#+BEGIN_SRC org + [[org-ql-search:property:author="Chris%20Wellons"?super-groups=((:auto-outline-path%20t))]] +#+END_SRC + +[2020-11-10 Tue 01:34] Okay, this seems to take care of all parameters: + +#+BEGIN_SRC elisp + (defun org-ql-search--link-open (path) + "Open Org QL query for current buffer at PATH. + PATH should be the part of an \"org-ql-search:\" URL after the + protocol. See, e.g. `org-ql-search--link-store'." + (require 'url-parse) + (require 'url-util) + (pcase-let* ((`(,query . ,params) (url-path-and-query + (url-parse-make-urlobj "org-ql-search" nil nil nil nil + path))) + (query (url-unhex-string query)) + (params (when params + (url-parse-query-string params))) + ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. + (sort (when (alist-get "sort" params nil nil #'string=) + (read (alist-get "sort" params nil nil #'string=)))) + (groups (when (alist-get "super-groups" params nil nil #'string=) + (read (alist-get "super-groups" params nil nil #'string=)))) + (title (when (alist-get "title" params nil nil #'string=) + (read (alist-get "title" params nil nil #'string=))))) + (org-ql-search (current-buffer) query + :sort sort + :super-groups groups + :title title))) + + (defun org-ql-search--link-store () + "Store a link to the current Org QL view. + Only views that search a single buffer may be linked to." + (require 'url-parse) + (require 'url-util) + (unless (or (bufferp org-ql-view-buffers-files) (= 1 (length org-ql-view-buffers-files))) + (user-error "Only views searching a single buffer may be linked")) + (when org-ql-view-query + (let* ((params (list (when org-ql-view-super-groups + (list "super-groups" (prin1-to-string org-ql-view-super-groups))) + (when org-ql-view-sort + (list "sort" (prin1-to-string org-ql-view-sort))) + (when org-ql-view-title + (list "title" (prin1-to-string org-ql-view-title))))) + (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) + "?" (url-build-query-string (delete nil params)))) + (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil + filename)))) + (org-store-link-props + :type "org-ql-search" + :link url + :description (concat "org-ql-search: " org-ql-view-title))) + t)) +#+END_SRC + +**** DONE For all parameters + +*** DONE Bookmarks + +[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. + +*** DONE Access saved query from saved query list + +*** DONE Save query from ql-agenda buffer + ** PROJECT [#A] Group tag support *** UNDERWAY Benchmarking tags searches without and with new group-tags support From 6970a952ba60209deac142e34c1f8bafeea20836 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:34:34 -0600 Subject: [PATCH 181/560] Fix: (org-ql-search.el) Require map Need to explicitly load it so that map 2.1 will be loaded when the file is byte-compiled, otherwise the pcase map expansions will fail. --- org-ql-search.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-search.el b/org-ql-search.el index c771a08..0bd02f2 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -31,6 +31,7 @@ (require 'dash) (require 'f) +(require 'map) (require 'org-super-agenda) (require 's) From 0101bbebdedcd1e4f1be2507d02536cd56c0df43 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:35:24 -0600 Subject: [PATCH 182/560] Comment: Remove useless package header Not the main library file. --- org-ql-view.el | 1 - 1 file changed, 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index 0bb873a..e98cfec 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -2,7 +2,6 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Package-Requires: ((transient) (map "2.0")) ;;; Commentary: From 04c94bc141937d5d9ef3130969380b41894c7786 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:36:41 -0600 Subject: [PATCH 183/560] Change: (org-ql-view.el) Rename bookmark functions They shouldn't be private functions, especially since one is autoloaded. --- org-ql-view.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index e98cfec..2e626bf 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -443,7 +443,7 @@ subsequent refreshing of the buffer: `org-ql-view-buffers-files', (null (org-ql-view--buffer buffer)) (buffer buffer)))) (with-current-buffer buffer - (setq-local bookmark-make-record-function #'org-ql-view--bookmark-make-record) + (setq-local bookmark-make-record-function #'org-ql-view-bookmark-make-record) (use-local-map org-ql-view-map) ;; Prepare buffer, saving data for refreshing. (cl-loop for symbol in vars @@ -541,7 +541,7 @@ dates in the past, and negative for dates in the future." (require 'bookmark) -(defun org-ql-view--bookmark-make-record () +(defun org-ql-view-bookmark-make-record () "Return a bookmark record for the current Org QL View buffer." (cl-labels ((file-nameize (b-f) (or (buffer-file-name b-f) @@ -559,11 +559,11 @@ dates in the past, and negative for dates in the future." collect (file-nameize b-f)))))) (list (concat "Org QL View: " org-ql-view-title) (cons 'org-ql-view-plist plist) - (cons 'handler #'org-ql-view--bookmark-handler) + (cons 'handler #'org-ql-view-bookmark-handler) (cons 'position (point)))))) ;;;###autoload -(defun org-ql-view--bookmark-handler (bookmark) +(defun org-ql-view-bookmark-handler (bookmark) "Show Org QL View BOOKMARK in current buffer." ;; FIXME: Getting "(void-variable super-groups)" errors when this function is byte-compiled, ;; but not when it's interpreted! Using (:super-groups super-groups) instead of just From b0e8fa27348b43ed9da88b0751044c335c7619a0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:37:48 -0600 Subject: [PATCH 184/560] Tidy: Indentation --- org-ql-view.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 2e626bf..f2c1479 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -844,7 +844,7 @@ return an empty string." (org-element-property :raw-value it) (org-link-display-format it))) (todo-keyword (-some--> (org-element-property :todo-keyword element) - (org-ql-view--add-todo-face it))) + (org-ql-view--add-todo-face it))) (tag-list (if org-use-tag-inheritance ;; MAYBE: Use our own variable instead of `org-use-tag-inheritance'. (if-let ((marker (or (org-element-property :org-hd-marker element) @@ -868,9 +868,9 @@ return an empty string." (org-add-props it nil 'face 'org-tag)))) ;; (category (org-element-property :category element)) (priority-string (-some->> (org-element-property :priority element) - (char-to-string) - (format "[#%s]") - (org-ql-view--add-priority-face))) + (char-to-string) + (format "[#%s]") + (org-ql-view--add-priority-face))) (habit-property (org-with-point-at (org-element-property :begin element) (when (org-is-habit-p) (org-habit-parse-todo)))) From 4b557857d3e8d3dc78e10faa9bee1209e3e8999f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:38:57 -0600 Subject: [PATCH 185/560] Tidy: Indentation --- tests/test-org-ql.el | 912 +++++++++++++++++++++---------------------- 1 file changed, 456 insertions(+), 456 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 93a042d..51a2e3d 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -116,13 +116,13 @@ Based on Buttercup macro `it'." (if body `(progn (buttercup-it ,(concat description " (preamble) ") - (lambda () - (let ((org-ql-use-preamble t)) - ,@body))) + (lambda () + (let ((org-ql-use-preamble t)) + ,@body))) (buttercup-it ,(concat description " (no preamble)") - (lambda () - (let ((org-ql-use-preamble nil)) - ,@body)))) + (lambda () + (let ((org-ql-use-preamble nil)) + ,@body)))) `(buttercup-xit ,description))) (cl-defmacro org-ql-expect (ql-args results &key (buffer 'org-ql-test-buffer)) @@ -421,339 +421,339 @@ RESULTS should be a list of strings as returned by (describe "(ancestors)" (org-ql-it "without sub-query" - (org-ql-expect ((ancestors)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((ancestors)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((ancestors (heading "universe"))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((ancestors (heading "universe"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(parent)" (org-ql-it "without sub-query" - (org-ql-expect ((parent)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((parent)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((parent (and (todo) (priority "A")))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((parent (and (todo) (priority "A")))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(category)" (org-ql-it "without arguments" - (expect (length (org-ql org-ql-test-buffer - (category))) - :to-equal org-ql-test-num-headings)) + (expect (length (org-ql org-ql-test-buffer + (category))) + :to-equal org-ql-test-num-headings)) (org-ql-it "with a category" - (org-ql-expect ((category "ambition")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) + (org-ql-expect ((category "ambition")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(children)" (org-ql-it "without arguments" - (org-ql-expect ((children)) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) + (org-ql-expect ((children)) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((children (todo "CHECK"))) - '("Recurring"))) + (org-ql-expect ((children (todo "CHECK"))) + '("Recurring"))) (org-ql-it "with grandchildren query" - ;; It's really cool how this works. It's so simple. - (org-ql-expect ((children (children "moon"))) - '("Take over the universe")))) + ;; It's really cool how this works. It's so simple. + (org-ql-expect ((children (children "moon"))) + '("Take over the universe")))) (describe "(descendants)" (org-ql-it "without arguments" - (org-ql-expect ((descendants)) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) + (org-ql-expect ((descendants)) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((descendants (todo "CHECK"))) - '("Recurring"))) + (org-ql-expect ((descendants (todo "CHECK"))) + '("Recurring"))) (org-ql-it "with granddescendants query" - (org-ql-expect ((descendants (descendants "moon"))) - '("Take over the universe"))) + (org-ql-expect ((descendants (descendants "moon"))) + '("Take over the universe"))) (org-ql-it "with query that should not match parent" - ;; This test would fail if the `descendants' predicate did not properly exclude - ;; the parent heading by narrowing the buffer to begin at the first child. - (org-ql-expect ((and (descendants (todo "WAITING")) - (not (descendants (todo "TODO" "NEXT"))))) - '("Take over the moon")))) + ;; This test would fail if the `descendants' predicate did not properly exclude + ;; the parent heading by narrowing the buffer to begin at the first child. + (org-ql-expect ((and (descendants (todo "WAITING")) + (not (descendants (todo "TODO" "NEXT"))))) + '("Take over the moon")))) (describe "(clocked)" (org-ql-it "without arguments" - (org-ql-expect ((clocked)) - '("Learn universal sign language"))) + (org-ql-expect ((clocked)) + '("Learn universal sign language"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((clocked 10)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked 10)) + '("Learn universal sign language")))) (org-ql-it ":from a timestamp" - (org-ql-expect ((clocked :from "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06")) - nil)) + (org-ql-expect ((clocked :from "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :from "2017-07-06")) + nil)) (org-ql-it ":from today" - (org-ql-then - (org-ql-expect ((clocked :from today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :from today)) + '("Learn universal sign language")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((clocked :to "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :to "2017-07-04")) - nil)) + (org-ql-expect ((clocked :to "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :to "2017-07-04")) + nil)) (org-ql-it ":to today" - (org-ql-then - (org-ql-expect ((clocked :to today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :to today)) + '("Learn universal sign language")))) (org-ql-it ":on a date" - (org-ql-expect ((clocked :on "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :on "2018-12-02")) - nil)) + (org-ql-expect ((clocked :on "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :on "2018-12-02")) + nil)) (org-ql-it ":on today" - (org-ql-then - (org-ql-expect ((clocked :on today)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((clocked :on today)) + '("Learn universal sign language")))) (org-ql-it "within a range (:from and :to)" - (org-ql-expect ((clocked :from "2017-07-04" :to "2018-12-11")) - '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06" :to "2018-12-11")) - nil) - (org-ql-expect ((clocked :from "2017-07-01" :to "2017-07-04")) - nil))) + (org-ql-expect ((clocked :from "2017-07-04" :to "2018-12-11")) + '("Learn universal sign language")) + (org-ql-expect ((clocked :from "2017-07-06" :to "2018-12-11")) + nil) + (org-ql-expect ((clocked :from "2017-07-01" :to "2017-07-04")) + nil))) (describe "(closed)" (org-ql-it "without arguments" - (org-ql-expect ((closed)) - '("Learn universal sign language"))) + (org-ql-expect ((closed)) + '("Learn universal sign language"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((closed 10)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((closed 10)) + '("Learn universal sign language")))) (org-ql-it ":on" - (org-ql-expect ((closed :on "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :on today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :on "2019-06-09")) - nil)) + (org-ql-expect ((closed :on "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :on today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :on "2019-06-09")) + nil)) (org-ql-it ":from" - (org-ql-expect ((closed :from "2017-07-04")) - '("Learn universal sign language")) - (org-ql-expect ((closed :from "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :from today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :from "2017-07-06")) - nil)) + (org-ql-expect ((closed :from "2017-07-04")) + '("Learn universal sign language")) + (org-ql-expect ((closed :from "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :from today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :from "2017-07-06")) + nil)) (org-ql-it ":to" - (org-ql-expect ((closed :to "2017-07-04")) - nil) - (org-ql-expect ((closed :to "2017-07-05")) - '("Learn universal sign language")) - (org-ql-then - (org-ql-expect ((closed :to today)) - '("Learn universal sign language"))) - (org-ql-expect ((closed :to "2017-07-06")) - '("Learn universal sign language")))) + (org-ql-expect ((closed :to "2017-07-04")) + nil) + (org-ql-expect ((closed :to "2017-07-05")) + '("Learn universal sign language")) + (org-ql-then + (org-ql-expect ((closed :to today)) + '("Learn universal sign language"))) + (org-ql-expect ((closed :to "2017-07-06")) + '("Learn universal sign language")))) (describe "(deadline)" (org-ql-it "without arguments" - (org-ql-expect ((deadline)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) + (org-ql-expect ((deadline)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) (org-ql-it "auto" - (org-ql-then - (org-ql-expect ((deadline auto)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + (org-ql-then + (org-ql-expect ((deadline auto)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((deadline 2)) - '("Take over the world" "/r/emacs")))) + (org-ql-then + (org-ql-expect ((deadline 2)) + '("Take over the world" "/r/emacs")))) (org-ql-it ":on" - (org-ql-expect ((deadline :on "2017-07-05")) - '("/r/emacs")) - (org-ql-then - (org-ql-expect ((deadline :on today)) - '("/r/emacs"))) + (org-ql-expect ((deadline :on "2017-07-05")) + '("/r/emacs")) + (org-ql-then + (org-ql-expect ((deadline :on today)) + '("/r/emacs"))) - (org-ql-expect ((deadline :on "2019-06-09")) - nil)) + (org-ql-expect ((deadline :on "2019-06-09")) + nil)) (org-ql-it ":from" - (org-ql-expect ((deadline :from "2017-07-04")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((deadline :from "2018-07-06")) - nil) - (org-ql-then - (org-ql-expect ((deadline :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + (org-ql-expect ((deadline :from "2017-07-04")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-expect ((deadline :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-expect ((deadline :from "2017-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-expect ((deadline :from "2018-07-06")) + nil) + (org-ql-then + (org-ql-expect ((deadline :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it ":to" - (org-ql-expect ((deadline :to "2017-07-04")) - nil) - (org-ql-expect ((deadline :to "2017-07-05")) - '("/r/emacs")) - (org-ql-expect ((deadline :to "2018-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-then - (org-ql-expect ((deadline :to today)) - '("/r/emacs"))))) + (org-ql-expect ((deadline :to "2017-07-04")) + nil) + (org-ql-expect ((deadline :to "2017-07-05")) + '("/r/emacs")) + (org-ql-expect ((deadline :to "2018-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (org-ql-then + (org-ql-expect ((deadline :to today)) + '("/r/emacs"))))) (org-ql-it "(done)" - (org-ql-expect ((done)) - '("Learn universal sign language"))) + (org-ql-expect ((done)) + '("Learn universal sign language"))) (org-ql-it "(habit)" - (org-ql-expect ((habit)) - '("Practice leaping tall buildings in a single bound"))) + (org-ql-expect ((habit)) + '("Practice leaping tall buildings in a single bound"))) (describe "(heading)" (org-ql-it "with one argument" - (org-ql-expect ((heading "world")) - ;; NOTE: This--correctly--does not match the "Skype with president of - ;; Antarctica" heading, which has the tag ":world:" in its heading line. - '("Take over the world"))) + (org-ql-expect ((heading "world")) + ;; NOTE: This--correctly--does not match the "Skype with president of + ;; Antarctica" heading, which has the tag ":world:" in its heading line. + '("Take over the world"))) (org-ql-it "with two arguments" - (org-ql-expect ((heading "Take over" "world")) - '("Take over the world")))) + (org-ql-expect ((heading "Take over" "world")) + '("Take over the world")))) (describe "(link)" (org-ql-it "without arguments" - (org-ql-expect ((link)) - '("/r/emacs"))) + (org-ql-expect ((link)) + '("/r/emacs"))) (org-ql-it "with description-or-target" - (org-ql-expect ((link "emacs")) - '("/r/emacs"))) + (org-ql-expect ((link "emacs")) + '("/r/emacs"))) (org-ql-it "with :description" - (org-ql-expect ((link :description "emacs")) - '("/r/emacs"))) + (org-ql-expect ((link :description "emacs")) + '("/r/emacs"))) (org-ql-it "with :target" - (org-ql-expect ((link :target "reddit.com")) - '("/r/emacs"))) + (org-ql-expect ((link :target "reddit.com")) + '("/r/emacs"))) (org-ql-it "with :description and :target" - (org-ql-expect ((link :description "emacs" :target "reddit.com")) - '("/r/emacs")))) + (org-ql-expect ((link :description "emacs" :target "reddit.com")) + '("/r/emacs")))) (describe "(outline-path)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path "symphony")) + '("Write a symphony"))) (org-ql-it "with two arguments" - (org-ql-expect ((outline-path "idea" "symphony")) - '("Write a symphony")))) + (org-ql-expect ((outline-path "idea" "symphony")) + '("Write a symphony")))) (describe "(outline-path-segment)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path-segment "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path-segment "symphony")) + '("Write a symphony"))) (org-ql-it "with a contiguous segment" - (org-ql-expect ((outline-path-segment "idea" "symphony")) - '("Write a symphony"))) + (org-ql-expect ((outline-path-segment "idea" "symphony")) + '("Write a symphony"))) (org-ql-it "with a non-contiguous segment" - (org-ql-expect ((outline-path-segment "data" "symphony")) - nil))) + (org-ql-expect ((outline-path-segment "data" "symphony")) + nil))) (describe "(path)" (org-ql-it "without arguments" - (org-ql-expect ((path)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with one argument" - (org-ql-expect ((path "data")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path "data")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two matching arguments" - (org-ql-expect ((path "data" "tests")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((path "data" "tests")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two arguments, one matching" - (org-ql-expect ((path "data" "nope")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (org-ql-expect ((path "data" "nope")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(planning)" (org-ql-it "without arguments" - (org-ql-expect ((planning)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((planning)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" - (org-ql-then - (org-ql-expect ((planning 2)) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((planning 2)) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on" - (org-ql-expect ((planning :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :on "2019-06-09")) - nil) - (org-ql-then - (org-ql-expect ((planning :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((planning :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :on "2019-06-09")) + nil) + (org-ql-then + (org-ql-expect ((planning :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((planning :from "2017-07-04")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-06")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-then - (org-ql-expect ((planning :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((planning :from "2017-07-04")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :from "2017-07-06")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-then + (org-ql-expect ((planning :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((planning :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((planning :to "2017-07-05")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :to "2018-07-06")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-then - (org-ql-expect ((planning :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) + (org-ql-expect ((planning :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((planning :to "2017-07-05")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((planning :to "2018-07-06")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-then + (org-ql-expect ((planning :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) (describe "(priority)" (org-ql-it "without arguments" - (org-ql-expect ((priority)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor"))) + (org-ql-expect ((priority)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor"))) (org-ql-it "with a priority" - (org-ql-expect ((priority "A")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority "A")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "= a priority" - (org-ql-expect ((priority = "A")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority = "A")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "< a priority" - (org-ql-expect ((priority < "B")) - '("Take over the moon" "Get haircut"))) + (org-ql-expect ((priority < "B")) + '("Take over the moon" "Get haircut"))) (org-ql-it "<= a priority" - (org-ql-expect ((priority <= "B")) - '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor"))) + (org-ql-expect ((priority <= "B")) + '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor"))) (org-ql-it "> a priority" - (org-ql-expect ((priority > "B")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) + (org-ql-expect ((priority > "B")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it ">= a priority" - (org-ql-expect ((priority >= "B")) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))) + (org-ql-expect ((priority >= "B")) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))) (describe "(property)" ;; MAYBE: Add support for (property) without arguments. @@ -761,84 +761,84 @@ RESULTS should be a list of strings as returned by ;; (org-ql-expect ((property)))) (org-ql-it "with a property" - (org-ql-expect ((property "agenda-group")) - '("Take over the universe" "Spaceship lease" "Recurring" "Write a symphony"))) + (org-ql-expect ((property "agenda-group")) + '("Take over the universe" "Spaceship lease" "Recurring" "Write a symphony"))) (org-ql-it "with a property and a value" - (org-ql-expect ((property "agenda-group" "plans")) - '("Take over the universe" "Write a symphony")))) + (org-ql-expect ((property "agenda-group" "plans")) + '("Take over the universe" "Write a symphony")))) (describe "(regexp)" (org-ql-it "with 1 argument" - (org-ql-expect ((regexp "Take over") - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ((regexp "Take over") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((regexp "Take over" "universe") - :sort todo) - '("Take over the universe"))) + (org-ql-expect ((regexp "Take over" "universe") + :sort todo) + '("Take over the universe"))) (org-ql-it "with a plain string" - (org-ql-expect ("Take over" - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ("Take over" + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with two plain strings in an OR" - (org-ql-expect ((or "Take over" "universe") - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-expect ((or "Take over" "universe") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "case-folding predicate with non-case-folding preamble" - ;; e.g. the (todo) predicate disables case-folding in its preamble, but that - ;; should not prevent case-folding in this and other predicates (issue #114). - (org-ql-expect ((and (todo "TODO") (regexp "take over")) - :sort todo) - '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) + ;; e.g. the (todo) predicate disables case-folding in its preamble, but that + ;; should not prevent case-folding in this and other predicates (issue #114). + (org-ql-expect ((and (todo "TODO") (regexp "take over")) + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) (describe "(scheduled)" (org-ql-it "without arguments" - (org-ql-expect ((scheduled)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((scheduled)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" - (org-ql-then - ;; Using -1 is the easiest way to exclude some results but not all for testing this. - (org-ql-expect ((scheduled -1)) - '("Skype with president of Antarctica")))) + (org-ql-then + ;; Using -1 is the easiest way to exclude some results but not all for testing this. + (org-ql-expect ((scheduled -1)) + '("Skype with president of Antarctica")))) (org-ql-it ":on" - (org-ql-expect ((scheduled :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :on "2019-06-09")) - nil) - (org-ql-then - (org-ql-expect ((scheduled :on today)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((scheduled :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :on "2019-06-09")) + nil) + (org-ql-then + (org-ql-expect ((scheduled :on today)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((scheduled :from "2017-07-04")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-06")) - nil) - (org-ql-then - (org-ql-expect ((scheduled :from today)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((scheduled :from "2017-07-04")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :from "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :from "2017-07-06")) + nil) + (org-ql-then + (org-ql-expect ((scheduled :from today)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((scheduled :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((scheduled :to "2017-07-05")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :to "2018-07-06")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-then - (org-ql-expect ((scheduled :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) + (org-ql-expect ((scheduled :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((scheduled :to "2017-07-05")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((scheduled :to "2018-07-06")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-then + (org-ql-expect ((scheduled :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) ;; TODO: Test (src) predicate. That will require modifying test data, which will be a ;; significant hassle. Manual testing shows that the predicate appears to work properly. @@ -846,288 +846,288 @@ RESULTS should be a list of strings as returned by (describe "(todo)" (org-ql-it "without arguments" - (org-ql-expect ((todo) - :sort todo) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((todo) + :sort todo) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 1 argument" - (org-ql-expect ((todo "WAITING") - :sort todo) - '("Visit the moon"))) + (org-ql-expect ((todo "WAITING") + :sort todo) + '("Visit the moon"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((todo "WAITING" "SOMEDAY") - :sort todo) - '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (org-ql-expect ((todo "WAITING" "SOMEDAY") + :sort todo) + '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(tags)" (org-ql-it "without arguments" - (org-ql-expect ((tags)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (tags))) - '("Recurring" "Sunrise/sunset" "Ideas"))) + (org-ql-expect ((tags)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) + (org-ql-expect ((not (tags))) + '("Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags "Emacs")) - '("/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs"))) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + (org-ql-expect ((tags "Emacs")) + '("/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags "Emacs"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((tags "Emacs" "space")) - '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs" "space"))) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + (org-ql-expect ((tags "Emacs" "space")) + '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags "Emacs" "space"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags "food")) - '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags "fruit")) - '("Fruit" "Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-inherited)" (org-ql-it "without arguments" - (org-ql-expect ((tags-inherited)) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (inherited-tags))) - '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-inherited)) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) + (org-ql-expect ((not (inherited-tags))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-inherited "Emacs")) - nil) - (org-ql-expect ((itags "ambition")) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (tags-i "ambition"))) - '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-inherited "Emacs")) + nil) + (org-ql-expect ((itags "ambition")) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) + (org-ql-expect ((not (tags-i "ambition"))) + '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((itags "personal" "world")) - '("Skype with president of Antarctica")) - (org-ql-expect ((not (tags-inherited "personal" "world"))) - ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". - '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((itags "personal" "world")) + '("Skype with president of Antarctica")) + (org-ql-expect ((not (tags-inherited "personal" "world"))) + ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". + '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-inherited "food")) - '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-inherited "fruit")) - '("Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-inherited "food")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-inherited "fruit")) + '("Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-local)" (org-ql-it "without arguments" - (org-ql-expect ((tags-local)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (local-tags))) - '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) + (org-ql-expect ((tags-local)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) + (org-ql-expect ((not (local-tags))) + '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-local "world")) - '("Take over the world" "Skype with president of Antarctica")) - (org-ql-expect ((ltags "ambition")) - '("Take over the universe")) - (org-ql-expect ((not (tags-l "ambition"))) - '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((tags-local "world")) + '("Take over the world" "Skype with president of Antarctica")) + (org-ql-expect ((ltags "ambition")) + '("Take over the universe")) + (org-ql-expect ((not (tags-l "ambition"))) + '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((ltags "personal" "world")) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) - (org-ql-expect ((not (tags-local "personal" "world"))) - '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) + (org-ql-expect ((ltags "personal" "world")) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) + (org-ql-expect ((not (tags-local "personal" "world"))) + '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-local "food")) - nil - :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-local "fruit")) - '("Fruit") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-local "food")) + nil + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags-local "fruit")) + '("Fruit") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-all), (tags&)" (org-ql-it "with 2 tags" - (org-ql-expect ((tags-all "universe" "personal")) - '("Practice leaping tall buildings in a single bound")) - (org-ql-expect ((tags& "ambition" "space")) - '("Visit Mars" "Visit the moon"))) + (org-ql-expect ((tags-all "universe" "personal")) + '("Practice leaping tall buildings in a single bound")) + (org-ql-expect ((tags& "ambition" "space")) + '("Visit Mars" "Visit the moon"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-all "food" "fruit")) - '("Fruit" "Blueberry" "Strawberry") - :buffer (org-ql-test-data-buffer "data2.org")))) + (org-ql-expect ((tags-all "food" "fruit")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(ts)" (describe "active" (org-ql-it "without arguments" - (org-ql-expect ((ts :type active)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts :type active)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-08" :type active)) - '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((ts :from "2019-06-08" :type active)) - nil) - (org-ql-then - (org-ql-expect ((ts :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-08" :type active)) + '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (org-ql-expect ((ts :from "2019-06-08" :type active)) + nil) + (org-ql-then + (org-ql-expect ((ts :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts :from 5)) - '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :from 5)) + '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type active)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type active)) - '("Skype with president of Antarctica")) - (org-ql-then - (org-ql-expect ((ts :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :to "2019-06-10" :type active)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04" :type active)) + '("Skype with president of Antarctica")) + (org-ql-then + (org-ql-expect ((ts :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts :to -1)) - '("Skype with president of Antarctica")))) + (org-ql-then + (org-ql-expect ((ts :to -1)) + '("Skype with president of Antarctica")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type active)) - '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09" :type active)) - nil) - (org-ql-then - (org-ql-expect ((ts :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :on "2017-07-05" :type active)) + '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2019-06-09" :type active)) + nil) + (org-ql-then + (org-ql-expect ((ts :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts-active :on 2)) - '("Take over the world"))))) + (org-ql-then + (org-ql-expect ((ts-active :on 2)) + '("Take over the world"))))) (describe "inactive" (org-ql-it "without arguments" - (org-ql-expect ((ts :type inactive)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts :type inactive)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-06" :type inactive)) - '("Visit the moon" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08" :type inactive)) - nil) - (org-ql-then - (org-ql-expect ((ts-inactive :from today)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-06" :type inactive)) + '("Visit the moon" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2019-06-08" :type inactive)) + nil) + (org-ql-then + (org-ql-expect ((ts-inactive :from today)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts-i :from 5)) - '("Visit the moon" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts-i :from 5)) + '("Visit the moon" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type inactive)) - '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type inactive)) - 'nil) - (org-ql-then - (org-ql-expect ((ts-inactive :to today)) - '("Learn universal sign language")))) + (org-ql-expect ((ts :to "2019-06-10" :type inactive)) + '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04" :type inactive)) + 'nil) + (org-ql-then + (org-ql-expect ((ts-inactive :to today)) + '("Learn universal sign language")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts-i :to 5)) - '("Learn universal sign language")))) + (org-ql-then + (org-ql-expect ((ts-i :to 5)) + '("Learn universal sign language")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type inactive)) - '("Learn universal sign language")) - (org-ql-expect ((ts :on "2019-06-09" :type inactive)) - nil) - (org-ql-then - (org-ql-expect ((ts-inactive :on today)) - '("Learn universal sign language")))) + (org-ql-expect ((ts :on "2017-07-05" :type inactive)) + '("Learn universal sign language")) + (org-ql-expect ((ts :on "2019-06-09" :type inactive)) + nil) + (org-ql-then + (org-ql-expect ((ts-inactive :on today)) + '("Learn universal sign language")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts-inactive :on 19)) - '("Visit the moon" "Rewrite Emacs in Common Lisp"))))) + (org-ql-then + (org-ql-expect ((ts-inactive :on 19)) + '("Visit the moon" "Rewrite Emacs in Common Lisp"))))) (describe "both" (org-ql-it "without arguments" - (org-ql-expect ((ts)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :type both)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) + (org-ql-expect ((ts)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :type both)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-05")) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2017-07-05" :type both)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08")) - nil) - (org-ql-expect ((ts :from "2019-06-08" :type both)) - nil) - (org-ql-then - (org-ql-expect ((ts :from today)) - '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :from "2017-07-05")) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2017-07-05" :type both)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :from "2019-06-08")) + nil) + (org-ql-expect ((ts :from "2019-06-08" :type both)) + nil) + (org-ql-then + (org-ql-expect ((ts :from today)) + '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" - (org-ql-then - (org-ql-expect ((ts :from -5)) - '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :from -5)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2017-07-06")) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-06" :type both)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04")) - '("Skype with president of Antarctica")) - (org-ql-expect ((ts :to "2017-07-04" :type both)) - '("Skype with president of Antarctica")) - (org-ql-then - (org-ql-expect ((ts :to today)) - '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :to "2017-07-06")) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-06" :type both)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :to "2017-07-04")) + '("Skype with president of Antarctica")) + (org-ql-expect ((ts :to "2017-07-04" :type both)) + '("Skype with president of Antarctica")) + (org-ql-then + (org-ql-expect ((ts :to today)) + '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" - (org-ql-then - (org-ql-expect ((ts :to 5)) - '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-then + (org-ql-expect ((ts :to 5)) + '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05")) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2017-07-05" :type both)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09")) - nil) - (org-ql-expect ((ts :on "2019-06-09" :type both)) - nil) - (org-ql-then - (org-ql-expect ((ts :on today)) - '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) + (org-ql-expect ((ts :on "2017-07-05")) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2017-07-05" :type both)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((ts :on "2019-06-09")) + nil) + (org-ql-expect ((ts :on "2019-06-09" :type both)) + nil) + (org-ql-then + (org-ql-expect ((ts :on today)) + '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" - (org-ql-then - (org-ql-expect ((ts :on 5)) - '("Renew membership in supervillain club")))))) + (org-ql-then + (org-ql-expect ((ts :on 5)) + '("Renew membership in supervillain club")))))) (describe "Compound queries" (org-ql-it "Tags and to-do" - (org-ql-expect ((and (todo "SOMEDAY") - (tags "Emacs"))) - '("Rewrite Emacs in Common Lisp")))))) + (org-ql-expect ((and (todo "SOMEDAY") + (tags "Emacs"))) + '("Rewrite Emacs in Common Lisp")))))) ;; Local Variables: ;; truncate-lines: t From b0b8c6334d0e70fc28ad7e560c0c771c0a027d54 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:43:53 -0600 Subject: [PATCH 186/560] Fix: (helm-org-ql.el) Compiler warnings --- helm-org-ql.el | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/helm-org-ql.el b/helm-org-ql.el index 059a965..e95bc5f 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -30,12 +30,9 @@ (eval-and-compile - (eval-when-compile - ;; Require these when compiling, but not necessarily on load. - (require 'org) - - (require 'org-ql) - (require 'org-ql-search)) + (require 'org) + (require 'org-ql) + (require 'org-ql-search) ;;;; Compatibility @@ -77,8 +74,10 @@ Based on `helm-map'.") :action (list (cons "Show view" #'org-ql-view))) "Helm source for `org-ql-views'.") - (defvar-local helm-org-ql-buffers-files nil - "Used for `helm-org-ql-save'.") + (with-no-warnings + ;; Silence compiler warning: "‘make-variable-buffer-local’ not called at toplevel" + (defvar-local helm-org-ql-buffers-files nil + "Used for `helm-org-ql-save'.")) ;;;; Customization From f8d671a7b8744c89f1497f0b05f17525ac3a8078 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:49:03 -0600 Subject: [PATCH 187/560] Docs: Thanks to @tpeacock19 --- README.org | 3 +++ org-ql.info | 42 +++++++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/README.org b/README.org index a4ee176..74d8c01 100644 --- a/README.org +++ b/README.org @@ -469,6 +469,9 @@ Simple links may also be written manually in either sexp or non-sexp form, like: *Internal* + When formatting entries for Org QL View buffers, use internal function for retrieving heading tags. This improves speed by using our cache, and it removes the need for a compatibility alias for Org versions before 9.3. +*Acknowledgments* ++ [[https://github.com/tpeacock19][tpeacock19]] for extensive help testing new features in this version. + ** 0.4.6 *Fixed* diff --git a/org-ql.info b/org-ql.info index 69af6fe..d215a50 100644 --- a/org-ql.info +++ b/org-ql.info @@ -849,6 +849,10 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog our cache, and it removes the need for a compatibility alias for Org versions before 9.3. + *Acknowledgments* + • tpeacock19 (https://github.com/tpeacock19) for extensive help + testing new features in this version. +  File: README.info, Node: 046, Next: 045, Prev: 05-pre, Up: Changelog @@ -1284,25 +1288,25 @@ Node: Links28046 Node: Tips28733 Node: Changelog29051 Node: 05-pre29690 -Node: 04630672 -Node: 04531075 -Node: 04431434 -Node: 04331791 -Node: 04231986 -Node: 04132145 -Node: 0432384 -Node: 03236315 -Node: 03136692 -Node: 0336889 -Node: 02339864 -Node: 02240092 -Node: 02140360 -Node: 0240559 -Node: 0144594 -Node: Notes44695 -Node: Comparison with Org Agenda searches44857 -Node: org-sidebar45729 -Node: License46008 +Node: 04630806 +Node: 04531209 +Node: 04431568 +Node: 04331925 +Node: 04232120 +Node: 04132279 +Node: 0432518 +Node: 03236449 +Node: 03136826 +Node: 0337023 +Node: 02339998 +Node: 02240226 +Node: 02140494 +Node: 0240693 +Node: 0144728 +Node: Notes44829 +Node: Comparison with Org Agenda searches44991 +Node: org-sidebar45863 +Node: License46142  End Tag Table From 2bed84aa1edeae12124d5661602080220f859544 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 19:54:13 -0600 Subject: [PATCH 188/560] Fix: (org-ql-view--contract-buffers-files) Don't check file exists If the buffer has no filename, this will signal an error. --- org-ql-view.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index f2c1479..bfe72ba 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -1032,7 +1032,7 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." "buffer") ((or 'org-agenda-files '(function org-agenda-files)) "org-agenda-files") - ((and (pred bufferp) (guard (file-exists-p (buffer-file-name buffers-files)))) + ((and (pred bufferp) (guard (buffer-file-name buffers-files))) (buffer-file-name buffers-files)) (_ (let ((print-length nil)) (prin1-to-string buffers-files)))))) From c2c7efed00b0f52f80538adee2d7eb7a53ea27c5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 20:38:05 -0600 Subject: [PATCH 189/560] Docs: Update readme Links can search more than just the current document now. --- README.org | 2 +- org-ql.info | 42 +++++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/README.org b/README.org index 74d8c01..9d68254 100644 --- a/README.org +++ b/README.org @@ -460,7 +460,7 @@ Simple links may also be written manually in either sexp or non-sexp form, like: + Predicate =link=, which matches descriptions and targets in Org links. + Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) + Dynamic block support. -+ Org link support (storing and opening links to Org QL View searches in the current document). ++ Org link support (storing and opening links to Org QL View searches). + Mascot. *Changed* diff --git a/org-ql.info b/org-ql.info index d215a50..2b5c83f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -836,8 +836,8 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog view restoration with Burly (https://github.com/alphapapa/burly.el).) • Dynamic block support. - • Org link support (storing and opening links to Org QL View searches - in the current document). + • Org link support (storing and opening links to Org QL View + searches). • Mascot. *Changed* @@ -1288,25 +1288,25 @@ Node: Links28046 Node: Tips28733 Node: Changelog29051 Node: 05-pre29690 -Node: 04630806 -Node: 04531209 -Node: 04431568 -Node: 04331925 -Node: 04232120 -Node: 04132279 -Node: 0432518 -Node: 03236449 -Node: 03136826 -Node: 0337023 -Node: 02339998 -Node: 02240226 -Node: 02140494 -Node: 0240693 -Node: 0144728 -Node: Notes44829 -Node: Comparison with Org Agenda searches44991 -Node: org-sidebar45863 -Node: License46142 +Node: 04630782 +Node: 04531185 +Node: 04431544 +Node: 04331901 +Node: 04232096 +Node: 04132255 +Node: 0432494 +Node: 03236425 +Node: 03136802 +Node: 0336999 +Node: 02339974 +Node: 02240202 +Node: 02140470 +Node: 0240669 +Node: 0144704 +Node: Notes44805 +Node: Comparison with Org Agenda searches44967 +Node: org-sidebar45839 +Node: License46118  End Tag Table From 6ab74454d0493105a1c57889c85800f4df962ebd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 20:45:10 -0600 Subject: [PATCH 190/560] Fix: (org-ql-view--expand-buffers-files) Remove eval support This prevents arbitrary code execution when opening "org-ql-search:" links. (The links feature was just pushed to master in the last day or so, and no stable release with the feature has been tagged.) This fix also means that arbitrary expressions are no longer accepted when interactively completing the buffers-files argument to org-ql-search (a worthy trade, I think; users who need to do that can call the function from Lisp). --- README.org | 1 - org-ql-search.el | 1 - org-ql-view.el | 1 - org-ql.info | 75 ++++++++++++++++++++++++------------------------ 4 files changed, 37 insertions(+), 41 deletions(-) diff --git a/README.org b/README.org index 9d68254..7863b92 100644 --- a/README.org +++ b/README.org @@ -106,7 +106,6 @@ Read ~QUERY~ and search with ~org-ql~. Interactively, prompt for these variable + ~buffer~: search the current buffer + ~all~: search all Org buffers + ~agenda~: search buffers returned by the function ~org-agenda-files~ -+ An expression which evaluates to a list of files/buffers + A space-separated list of file or buffer names ~GROUPS~: An ~org-super-agenda~ group set. See variable ~org-super-agenda-groups~. diff --git a/org-ql-search.el b/org-ql-search.el index 0bd02f2..3abc468 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -119,7 +119,6 @@ Interactively, may also be: - `all': search all Org buffers - `agenda': search buffers returned by the function `org-agenda-files' - `directory': search Org files in `org-directory' -- An expression which evaluates to a list of files/buffers - A space-separated list of file or buffer names QUERY: An `org-ql' query in either sexp or non-sexp form (see diff --git a/org-ql-view.el b/org-ql-view.el index bfe72ba..d7a34a8 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -1063,7 +1063,6 @@ The counterpart to `org-ql-view--contract-buffers-files'." ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) (buffer-list))) ("org-directory" (org-ql-search-directories-files)) - ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) (else (s-split (rx (1+ space)) else)))) (defun org-ql-view--complete-super-groups () diff --git a/org-ql.info b/org-ql.info index 2b5c83f..baf149e 100644 --- a/org-ql.info +++ b/org-ql.info @@ -214,7 +214,6 @@ Interactively, may also be: • ‘all’: search all Org buffers • ‘agenda’: search buffers returned by the function ‘org-agenda-files’ - • An expression which evaluates to a list of files/buffers • A space-separated list of file or buffer names ‘GROUPS’: An ‘org-super-agenda’ group set. See variable @@ -1270,43 +1269,43 @@ Node: Quelpa2428 Node: Usage2871 Node: Commands3269 Node: org-ql-search3742 -Node: helm-org-ql5456 -Node: org-ql-view5868 -Node: org-ql-view-sidebar6368 -Node: org-ql-view-recent-items6724 -Node: org-ql-sparse-tree7208 -Node: Queries8008 -Node: Non-sexp query syntax8916 -Node: General predicates10623 -Node: Ancestor/descendant predicates15838 -Node: Date/time predicates16966 -Node: Functions / Macros19621 -Node: Agenda-like views19876 -Node: Listing / acting-on results21281 -Node: Dynamic block25883 -Node: Links28046 -Node: Tips28733 -Node: Changelog29051 -Node: 05-pre29690 -Node: 04630782 -Node: 04531185 -Node: 04431544 -Node: 04331901 -Node: 04232096 -Node: 04132255 -Node: 0432494 -Node: 03236425 -Node: 03136802 -Node: 0336999 -Node: 02339974 -Node: 02240202 -Node: 02140470 -Node: 0240669 -Node: 0144704 -Node: Notes44805 -Node: Comparison with Org Agenda searches44967 -Node: org-sidebar45839 -Node: License46118 +Node: helm-org-ql5392 +Node: org-ql-view5804 +Node: org-ql-view-sidebar6304 +Node: org-ql-view-recent-items6660 +Node: org-ql-sparse-tree7144 +Node: Queries7944 +Node: Non-sexp query syntax8852 +Node: General predicates10559 +Node: Ancestor/descendant predicates15774 +Node: Date/time predicates16902 +Node: Functions / Macros19557 +Node: Agenda-like views19812 +Node: Listing / acting-on results21217 +Node: Dynamic block25819 +Node: Links27982 +Node: Tips28669 +Node: Changelog28987 +Node: 05-pre29626 +Node: 04630718 +Node: 04531121 +Node: 04431480 +Node: 04331837 +Node: 04232032 +Node: 04132191 +Node: 0432430 +Node: 03236361 +Node: 03136738 +Node: 0336935 +Node: 02339910 +Node: 02240138 +Node: 02140406 +Node: 0240605 +Node: 0144640 +Node: Notes44741 +Node: Comparison with Org Agenda searches44903 +Node: org-sidebar45775 +Node: License46054  End Tag Table From 689cfd68e78b69ff19666706b876db97b152bdb1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 11 Nov 2020 22:52:54 -0600 Subject: [PATCH 191/560] Fix: (-view--link-open) Set org-super-agenda-allow-unsafe-groups --- org-ql-view.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-view.el b/org-ql-view.el index d7a34a8..0255b76 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -617,6 +617,7 @@ protocol. See, e.g. `org-ql-view--link-store'." ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. (sort (--when-let (alist-get "sort" params nil nil #'string=) (read it))) + (org-super-agenda-allow-unsafe-groups nil) ; Disallow unsafe group selectors. (groups (--when-let (alist-get "super-groups" params nil nil #'string=) (read it))) (title (--when-let (alist-get "title" params nil nil #'string=) From a5d48868808a8ba59db360466f1c1b1060db16c5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 00:22:23 -0600 Subject: [PATCH 192/560] Fix: (org-ql-view--link-open) Safety check the sort parameter --- org-ql-view.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 0255b76..6945c45 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -615,8 +615,13 @@ protocol. See, e.g. `org-ql-view--link-store'." (query (url-unhex-string query)) (params (when params (url-parse-query-string params))) ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. - (sort (--when-let (alist-get "sort" params nil nil #'string=) - (read it))) + (sort (when-let* ((stored-string (alist-get "sort" params nil nil #'string=)) + (read-value (read stored-string))) + ;; Ensure the value is either a symbol or list of symbols (which excludes lambdas). + (unless (or (symbolp read-value) (cl-every #'symbolp read-value)) + (error "Potentially unsafe value found in link's SORT parameter (%s). Link not opened" + read-value)) + read-value)) (org-super-agenda-allow-unsafe-groups nil) ; Disallow unsafe group selectors. (groups (--when-let (alist-get "super-groups" params nil nil #'string=) (read it))) From 5e790c48acb91b5969f0147f591fdcd7dfecc7bd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 00:22:45 -0600 Subject: [PATCH 193/560] Tests: Add tests for link safety --- tests/test-org-ql.el | 91 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 51a2e3d..63a02cf 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1127,7 +1127,96 @@ RESULTS should be a list of strings as returned by (org-ql-it "Tags and to-do" (org-ql-expect ((and (todo "SOMEDAY") (tags "Emacs"))) - '("Rewrite Emacs in Common Lisp")))))) + '("Rewrite Emacs in Common Lisp"))))) + + (describe "Org link safety" + + ;; NOTE: These tests probably do not guarantee safety. Still, these tests are probably + ;; better than nothing. In fact, this is pretty cool: by testing for the specific error + ;; signal and the arguments to the error, I caught a mistake I made while writing these tests + ;; (leaving a closing bracket off one of the links), which caused that test to fail but for a + ;; different reason. Were it not for testing the specific error AND its arguments, that test + ;; case would have apparently passed, but it would have hidden the mistake in the test. + + ;; Also, while writing these tests, the version of org-super-agenda in the test sandbox does + ;; not have the fix applied yet, and the test for that apparently, correctly does not pass yet. + + (require 'org-ql-search) + (require 'org-ql-view) + + (cl-flet ((open-link + (link) (with-temp-buffer + (org-mode) + (insert link) + (backward-char 1) + (call-interactively #'org-open-at-point)))) + + (it "buffers-files parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'wrong-type-argument '(stringp ((quote (lambda nil (message "AHA")))))) + (expect (open-link unquoted-lambda-in-list-link) + :to-throw 'wrong-type-argument '(stringp ((lambda nil (message "AHA"))))))) + + (it "super-groups parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (quoted-expression-link "[[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]]") + (unquoted-expression-link "[[org-ql-search:todo:?super-groups%3D%22AHA%22]]") + (pred-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]") + (auto-map-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(listp lambda)) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(listp lambda)) + (expect (open-link quoted-expression-link) + :to-throw 'wrong-type-argument '(listp message)) + (expect (open-link unquoted-expression-link) + :to-throw 'error '("cl-etypecase failed: AHA, (symbol list)")) + + ;; FIXME: These two tests will not pass (i.e. they will not + ;; signal an error) until the version of org-super-agenda in + ;; the test sandbox is upgraded, which I'll do when MELPA + ;; packages the latest version. On the bright side, I just + ;; confirmed that, without the fix to org-super-agenda, + ;; these are vulnerable, which means that the test catches + ;; this problem and detects the fix. + (expect (open-link pred-selector-link) + :to-throw 'error '("Unsafe groups disallowed (:pred): (lambda (_) (message AHA))")) + (expect (open-link auto-map-selector-link) + :to-throw 'error '("Unsafe groups disallowed (:auto-map): ((lambda (_) (message AHA)))")))) + + (it "title parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (expression-link "[[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(characterp lambda)) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(characterp lambda)) + (expect (open-link expression-link) + :to-throw 'wrong-type-argument '(characterp message)))) + + (it "sort parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?sort=((lambda%20nil%20(message%20\"AHA\")))]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + (expect (open-link unquoted-lambda-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((quote (lambda (_ _) (message AHA))))). Link not opened")) + (expect (open-link unquoted-lambda-in-list-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((lambda nil (message AHA)))). Link not opened"))))))) ;; Local Variables: ;; truncate-lines: t From a069cf5b2cd1f0ef3430111feeae4e49765bf47a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 00:26:53 -0600 Subject: [PATCH 194/560] Notes: Update --- notes.org | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/notes.org b/notes.org index 3e9aea5..46214e1 100644 --- a/notes.org +++ b/notes.org @@ -70,8 +70,6 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] -- [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] -- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#outline-path-predicate][Outline path predicate]] - [[#recursive-queries][Recursive queries]] - [[#timeline-view][Timeline view]] @@ -80,7 +78,10 @@ - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] +- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] +- [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] - [[#dynamic-blocks][Dynamic blocks]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] @@ -1167,6 +1168,83 @@ Next steps: + [X] Discuss caching of group tag expansion. It seems like we ought to cache the expansions as well, because sibling headings (especially at level 1) ought to get their group tags re-expanded individually, even when we've already expanded them for another heading. + [X] Remove unused =result= variable +** PROJECT [#A] Checking links for unsafe parameters +:PROPERTIES: +:ID: ba70e375-eddb-40df-8892-fb418c1f70d1 +:END: +:LOGBOOK: +- State "PROJECT" from "UNDERWAY" [2020-11-12 Thu 00:26] +- State "UNDERWAY" from [2020-11-11 Wed 23:09] +:END: + +*** TODO Tag org-super-agenda 1.2 and bump required version in org-ql + +That /should/ force the version of org-super-agenda with the fix to be installed when org-ql is upgraded. + +*** UNDERWAY Add automated tests +:LOGBOOK: +- State "UNDERWAY" from "TODO" [2020-11-12 Thu 00:24] +- State "TODO" from "MAYBE" [2020-11-11 Wed 23:16] +- State "MAYBE" from [2020-11-11 Wed 23:15] +:END: + +Maybe impractical, but maybe we could at least test that potentially unsafe ones signal errors. + +[2020-11-12 Thu 00:24] Works better than I expected. All the tests seem to correctly pass, signaling the correct errors for the correct reasons--except for the tests specific to org-super-agenda. For that, I'm currently waiting for MELPA to build the version of org-super-agenda that has the fix applied, so I can install that into the test sandbox, and then those two tests should pass also. + +*** DONE Enumerate and test parameters and potentially unsafe types +CLOSED: [2020-11-11 Wed 23:26] +:LOGBOOK: +- State "DONE" from "UNDERWAY" [2020-11-11 Wed 23:26] +- State "UNDERWAY" from [2020-11-11 Wed 23:15] +:END: + +#+CAPTION: Template for making testable links +#+BEGIN_SRC org +[[org-ql-search:todo:?]] +#+END_SRC + +#+CAPTION: Expression to insert encoded values into template (after the =?=) +#+BEGIN_SRC elisp + (insert (url-hexify-string (concat "buffers-files=" (prin1-to-string '((lambda () (message "AHA"))))))) +#+END_SRC + ++ [X] Buffers-Files: Expanded by =org-ql-view--expand-buffers-files=: + - [X] Quoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Quoted lambda in list (safe): [[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]] + - [X] Unquoted lambda in list: (safe) [[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]] ++ [X] Groups + - [X] Quoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Quoted expression (safe): [[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]] + - [X] Unquoted expression (safe): [[org-ql-search:todo:?super-groups%3D%22AHA%22]] + - [X] ~:pred~ selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] + - [X] =:auto-map= selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] ++ [X] Title + - [X] Quoted lambda (produces the same encoded value as unquoted lambda): (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Expression: (safe) [[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]] ++ [X] Sort + - [X] Bare, quoted lambda: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Bare, unquoted lambda: (UNSAFE, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Quoted lambda in list: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]] + - [X] Unquoted lambda in a list: (UNSAFE, but caught now): [[org-ql-search:todo:?sort=((lambda%20nil%20(message%20"AHA")))]] + +For the query expression: + +1. String queries are parsed by the PEG parsing function (which I will probably rename soon), which should only allow known Org QL predicates, not arbitrary functions. For example: + + #+BEGIN_SRC elisp + (org-ql--plain-query "message:AHA") ;;=> (regexp "message:AHA") + (org-ql--plain-query '(message "AHA")) ;;=> (wrong-type-argument stringp (message "AHA")) + (org-ql--plain-query "(message \"AHA\"") ;;=> (and (regexp "(message") (regexp "AHA")) + #+END_SRC + +2. Sexp queries already prompt for confirmation, unless the user has set =org-ql-view-ask-unsafe-links= to nil. + +[2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. + ** DONE [#A] Dynamic blocks + *Tasks* From 284eda87e573ba66537797536b9f749fd9804a73 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 02:10:57 -0600 Subject: [PATCH 195/560] Fix: (org-ql-view--link-store) Test Org version See #147. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 6945c45..42a170e 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -648,6 +648,8 @@ protocol. See, e.g. `org-ql-view--link-store'." :title title))) (defvar org-ql-view--link-store-counter 0 + ;; TODO: When compatibility with Org <=9.1.4 is dropped, remove this. See + ;; . "Workaround for an idiosyncrasy of `org-store-link' that calls link-storing functions twice.") (defun org-ql-view--link-store () @@ -661,11 +663,13 @@ When opened, the link searches the buffer it's opened from." (cl-some #'bufferp org-ql-view-buffers-files)) ;; Buffers are unreadable, so they can't be linked to. (user-error "Views that search buffers rather than files can't be linked to")) - (cl-incf org-ql-view--link-store-counter) + (cl-incf org-ql-view--link-store-counter) ;; TODO: Remove when not supporting Org<=9.1.4. See other comment. (cl-flet ((prompt-for (buffers-files) ;; HACK: Use counter to avoid prompting the first of the ;; two times that `org-store-link' calls this function. - (when (cl-evenp org-ql-view--link-store-counter) + ;; TODO: Remove the version check when not supporting Org<=9.1.4. See other comment. + (when (or (version< "9.1.4" (org-version)) + (cl-evenp org-ql-view--link-store-counter)) (pcase-exhaustive (completing-read (format "Link to search file containing inserted link or %s? " buffers-files) (list "containing file" buffers-files) nil t) From f63012dd5adb9d3842a7790c5cbc45edf88fbcb2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 02:43:08 -0600 Subject: [PATCH 196/560] Fix: (org-ql-view--link-store) Rejection of unlinkable buffers Also, remove the Org <=9.1.4 compatibility code. It's not worth it. I'm probably the only person who needs it, anyway, and I can live with the double-call until I upgrade my Org version. Fixes #148. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 42a170e..843211e 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -647,11 +647,6 @@ protocol. See, e.g. `org-ql-view--link-store'." :super-groups groups :title title))) -(defvar org-ql-view--link-store-counter 0 - ;; TODO: When compatibility with Org <=9.1.4 is dropped, remove this. See - ;; . - "Workaround for an idiosyncrasy of `org-store-link' that calls link-storing functions twice.") - (defun org-ql-view--link-store () "Store a link to the current Org QL view. When opened, the link searches the buffer it's opened from." @@ -659,22 +654,20 @@ When opened, the link searches the buffer it's opened from." (require 'url-util) (when org-ql-view-query ;; Only Org QL View buffers should have `org-ql-view-query' set. - (when (or (bufferp org-ql-view-buffers-files) - (cl-some #'bufferp org-ql-view-buffers-files)) - ;; Buffers are unreadable, so they can't be linked to. - (user-error "Views that search buffers rather than files can't be linked to")) - (cl-incf org-ql-view--link-store-counter) ;; TODO: Remove when not supporting Org<=9.1.4. See other comment. (cl-flet ((prompt-for (buffers-files) - ;; HACK: Use counter to avoid prompting the first of the - ;; two times that `org-store-link' calls this function. - ;; TODO: Remove the version check when not supporting Org<=9.1.4. See other comment. - (when (or (version< "9.1.4" (org-version)) - (cl-evenp org-ql-view--link-store-counter)) - (pcase-exhaustive - (completing-read (format "Link to search file containing inserted link or %s? " buffers-files) - (list "containing file" buffers-files) nil t) - ("containing file" nil) - (buffers-files (prin1-to-string buffers-files)))))) + (pcase-exhaustive + (completing-read (format "Link to search file containing inserted link or %s? " buffers-files) + (list "containing file" buffers-files) nil t) + ("containing file" nil) + (buffers-files (prin1-to-string buffers-files)))) + (string-or-file-buffer-p + (thing) (or (stringp thing) + (and (bufferp thing) + (buffer-file-name thing))))) + (unless (or (string-or-file-buffer-p org-ql-view-buffers-files) + (and (listp org-ql-view-buffers-files) + (cl-every #'string-or-file-buffer-p org-ql-view-buffers-files))) + (user-error "Views that search non-file-backed buffers can't be linked to")) (let* ((query-string (--if-let (org-ql--query-sexp-to-string org-ql-view-query) it (prin1-to-string (org-ql-view--format-query org-ql-view-query)))) (buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) From cbd4ea89f4f044719a01cf189a2a85efeaaec889 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 03:18:16 -0600 Subject: [PATCH 197/560] Notes: Update --- notes.org | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/notes.org b/notes.org index 46214e1..451e6fb 100644 --- a/notes.org +++ b/notes.org @@ -18,19 +18,18 @@ ** Underway -[[org-ql-search:%2528todo%2520%2522UNDERWAY%2522%2529?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] +[[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] #+BEGIN: org-ql :query (todo "UNDERWAY") :columns ((priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" | P | Keyword | Heading | |---+----------+--------------------------------------------------------------------| -| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | -| A | UNDERWAY | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | | B | UNDERWAY | [[Recursive queries][Recursive queries]] | | B | UNDERWAY | [[Timeline view][Timeline view]] | | B | UNDERWAY | [["Node" caching]["Node" caching]] | | B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | +| | UNDERWAY | [[Add automated tests][Add automated tests]] | #+END: ** To-do @@ -46,7 +45,7 @@ | A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | | A | TODO | [[Save views to dynamic blocks][Save views to dynamic blocks]] | | A | TODO | [[Consider how to "secure" searches from links and dynamic blocks][Consider how to "secure" searches from links and dynamic blocks]] | -| A | UNDERWAY | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | +| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | #+END: * [#A] Tasks @@ -64,6 +63,7 @@ - [[#add-more-sorters][Add more sorters?]] - [[#default-sort][Default sort]] - [[#partial-match-for-property-queries][Partial match for property queries]] +- [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] - [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] - [[#normalize-queries][Normalize queries]] - [[#update-view-screenshots][Update view screenshots]] @@ -162,6 +162,10 @@ e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. +** TODO [#B] Move this notes file into an orphan =meta/notes= branch + +[2020-11-12 Thu 03:17] Will probably have to merge or delete some WIP branches first, otherwise they'll probably get conflicts. + ** TODO [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] [2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. @@ -1181,7 +1185,7 @@ Next steps: That /should/ force the version of org-super-agenda with the fix to be installed when org-ql is upgraded. -*** UNDERWAY Add automated tests +*** DONE Add automated tests :LOGBOOK: - State "UNDERWAY" from "TODO" [2020-11-12 Thu 00:24] - State "TODO" from "MAYBE" [2020-11-11 Wed 23:16] @@ -1245,7 +1249,13 @@ For the query expression: [2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. -** DONE [#A] Dynamic blocks +** PROJECT Dynamic blocks + +*** TODO [#B] Save view to dynamic block + +[2020-11-12 Thu 03:23] A command to do this would be very helpful. + +*** DONE [#A] Implement dynamic blocks + *Tasks* - [X] Merge code From 337bfa6695bb5c3df83904311c0350499a2f3751 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 04:09:57 -0600 Subject: [PATCH 198/560] Add: (tags-regexp, tags*) Predicate --- README.org | 3 +++ org-ql.el | 20 ++++++++++++++ org-ql.info | 64 ++++++++++++++++++++++++-------------------- tests/test-org-ql.el | 28 +++++++++++++++++++ 4 files changed, 86 insertions(+), 29 deletions(-) diff --git a/README.org b/README.org index 7863b92..6fcfc92 100644 --- a/README.org +++ b/README.org @@ -219,6 +219,8 @@ Arguments are listed next to predicate names, where applicable. - Aliases: ~local-tags~, ~tags-l~, ~ltags~. + =tags-all (tags)= :: Return non-nil if current heading includes all of ~TAGS~. Tests both inherited and local tags. - Aliases: ~tags&~. ++ =tags-regexp (&rest regexps)= :: Return non-nil if current heading has tags matching one or more of ~REGEXPS~. Tests both inherited and local tags. + - Aliases: ~tags*~. + =todo (&optional keywords)= :: Return non-nil if current heading is a ~TODO~ item. With ~KEYWORDS~, return non-nil if its keyword is one of ~KEYWORDS~ (a list of strings). When called without arguments, only matches non-done tasks (i.e. does not match keywords in ~org-done-keywords~). *** Ancestor/descendant predicates @@ -457,6 +459,7 @@ Simple links may also be written manually in either sexp or non-sexp form, like: *Added* + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. + Predicate =link=, which matches descriptions and targets in Org links. ++ Predicate ~tags-regexp~ (alias: ~tags*~), which matches regexps against entry tags (e.g, helpful when a tag might end in "s"). + Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. =C-x r m= and shown with, e.g. =C-x r b=. (This also enables view restoration with [[https://github.com/alphapapa/burly.el][Burly]].) + Dynamic block support. + Org link support (storing and opening links to Org QL View searches). diff --git a/org-ql.el b/org-ql.el index f6639c4..dc6ee24 100644 --- a/org-ql.el +++ b/org-ql.el @@ -672,6 +672,7 @@ Replaces bare strings with (regexp) selectors, and appropriate ;; Inherited and local predicate aliases. (`(,(or 'tags-i 'itags 'inherited-tags) . ,tags) `(tags-inherited ,@tags)) (`(,(or 'tags-l 'ltags 'local-tags) . ,tags) `(tags-local ,@tags)) + (`(,(or 'tags*) . ,regexps) `(tags-regexp ,@regexps)) ;; Timestamps (`(,(or 'ts-active 'ts-a) . ,rest) `(ts :type active ,@rest)) @@ -1153,6 +1154,25 @@ If TAGS is nil, return non-nil if heading has any local tags." (otherwise (when (tags-p local) (seq-intersection tags local))))))) +(org-ql--defpred (tags-regexp tags*) (&rest regexps) + "Return non-nil if current heading has tags matching one or more of REGEXPS. +Tests both inherited and local tags." + (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((inherited local) (org-ql--tags-at (point)))) + (cl-typecase regexps + (null (or (tags-p inherited) + (tags-p local))) + (otherwise (or (when (tags-p inherited) + (cl-loop for tag in inherited + thereis (cl-loop for regexp in regexps + thereis (string-match regexp tag)))) + (when (tags-p local) + (cl-loop for tag in local + thereis (cl-loop for regexp in regexps + thereis (string-match regexp tag)))))))))) + (org-ql--defpred level (level-or-comparator &optional level) "Return non-nil if current heading's outline level matches arguments. The following forms are accepted: diff --git a/org-ql.info b/org-ql.info index baf149e..3d86d66 100644 --- a/org-ql.info +++ b/org-ql.info @@ -455,6 +455,10 @@ Arguments are listed next to predicate names, where applicable. Return non-nil if current heading includes all of ‘TAGS’. Tests both inherited and local tags. • Aliases: ‘tags&’. +‘tags-regexp (&rest regexps)’ + Return non-nil if current heading has tags matching one or more of + ‘REGEXPS’. Tests both inherited and local tags. + • Aliases: ‘tags*’. ‘todo (&optional keywords)’ Return non-nil if current heading is a ‘TODO’ item. With ‘KEYWORDS’, return non-nil if its keyword is one of ‘KEYWORDS’ (a @@ -830,6 +834,8 @@ File: README.info, Node: 05-pre, Next: 046, Up: Changelog search/view buffers. • Predicate link, which matches descriptions and targets in Org links. + • Predicate ‘tags-regexp’ (alias: ‘tags*’), which matches regexps + against entry tags (e.g, helpful when a tag might end in "s"). • Emacs bookmark support: Org QL View buffers can be bookmarked with, e.g. C-x r m and shown with, e.g. C-x r b. (This also enables view restoration with Burly @@ -1277,35 +1283,35 @@ Node: org-ql-sparse-tree7144 Node: Queries7944 Node: Non-sexp query syntax8852 Node: General predicates10559 -Node: Ancestor/descendant predicates15774 -Node: Date/time predicates16902 -Node: Functions / Macros19557 -Node: Agenda-like views19812 -Node: Listing / acting-on results21217 -Node: Dynamic block25819 -Node: Links27982 -Node: Tips28669 -Node: Changelog28987 -Node: 05-pre29626 -Node: 04630718 -Node: 04531121 -Node: 04431480 -Node: 04331837 -Node: 04232032 -Node: 04132191 -Node: 0432430 -Node: 03236361 -Node: 03136738 -Node: 0336935 -Node: 02339910 -Node: 02240138 -Node: 02140406 -Node: 0240605 -Node: 0144640 -Node: Notes44741 -Node: Comparison with Org Agenda searches44903 -Node: org-sidebar45775 -Node: License46054 +Node: Ancestor/descendant predicates15972 +Node: Date/time predicates17100 +Node: Functions / Macros19755 +Node: Agenda-like views20010 +Node: Listing / acting-on results21415 +Node: Dynamic block26017 +Node: Links28180 +Node: Tips28867 +Node: Changelog29185 +Node: 05-pre29824 +Node: 04631063 +Node: 04531466 +Node: 04431825 +Node: 04332182 +Node: 04232377 +Node: 04132536 +Node: 0432775 +Node: 03236706 +Node: 03137083 +Node: 0337280 +Node: 02340255 +Node: 02240483 +Node: 02140751 +Node: 0240950 +Node: 0144985 +Node: Notes45086 +Node: Comparison with Org Agenda searches45248 +Node: org-sidebar46120 +Node: License46399  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 63a02cf..d31a08f 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -962,6 +962,34 @@ RESULTS should be a list of strings as returned by '("Fruit" "Blueberry" "Strawberry") :buffer (org-ql-test-data-buffer "data2.org")))) + (describe "(tags-regexp), (tags*)" + + (org-ql-it "without arguments" + (org-ql-expect ((tags-regexp)) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) + (org-ql-expect ((not (tags*))) + '("Recurring" "Sunrise/sunset" "Ideas"))) + + (org-ql-it "with a tag regexp" + (org-ql-expect ((tags-regexp "Emac")) + '("/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags* "Emac"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + + (org-ql-it "with 2 tag regexps" + (org-ql-expect ((tags-regexp "Emac" "spac")) + '("Visit Mars" "Visit the moon" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Rewrite Emacs in Common Lisp")) + (org-ql-expect ((not (tags* "Emac" "spac"))) + '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) + + (org-ql-it "with regexp matching file tags" + (org-ql-expect ((tags-regexp "foo")) + '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") + :buffer (org-ql-test-data-buffer "data2.org")) + (org-ql-expect ((tags* "frui")) + '("Fruit" "Blueberry" "Strawberry") + :buffer (org-ql-test-data-buffer "data2.org")))) + (describe "(ts)" (describe "active" From 2b21871a02f865fc5c16a030442af3fd58bb9c60 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 04:13:47 -0600 Subject: [PATCH 199/560] Notes: Update --- notes.org | 540 +++++++++++++++++++++++++++--------------------------- 1 file changed, 270 insertions(+), 270 deletions(-) diff --git a/notes.org b/notes.org index 451e6fb..bbfa442 100644 --- a/notes.org +++ b/notes.org @@ -267,233 +267,6 @@ To implement this with good performance probably needs an outline-path cache. I [2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. -** UNDERWAY [#B] Recursive queries - -For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. - -This works pretty well. It needs polishing, and some refactoring so items can be indented completely (rather than leaving the keyword unindented, as it is now). - -#+BEGIN_SRC elisp - (cl-defun org-ql-agenda-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil - (org-ql-agenda--agenda nil nil - :entries))))) - - (cl-defun org-ql-select-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil)))) -#+END_SRC - -** UNDERWAY [#B] Timeline view -:PROPERTIES: -:ID: 00573552-ffe9-4608-8904-7f6c73246b6d -:END: - -e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: - -#+BEGIN_SRC elisp - (cl-defun org-ql-timeline (buffers-files query) - (let ((results - (org-ql-select buffers-files - query :action - (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (timestamps - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (ts-parse-org (match-string 0)))) - (timestamp-strings - (->> timestamps - (-sort #'ts<) - (--map (concat " " (ts-format it)))))) - (s-join "\n" (cons heading-string timestamp-strings)))) - :sort '(date)))) - (org-ql-agenda--agenda nil nil :strings results))) - - (org-ql-timeline (org-agenda-files) - '(and "Emacs" (ts))) - - ;; More timeline-like version, organized by date rather than task. - - (cl-defun org-ql-timeline* (buffers-files query &key filter-ts) - (let* ((ts-ht (ht)) - (results (org-ql-select buffers-files - query - :action (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (date-timestamps - ;; Each one set to 00:00:00. - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (->> (match-string 0) - ts-parse-org - (ts-apply :hour 0 :minute 0 :second 0))))) - (setf date-timestamps (delete-dups date-timestamps)) - (when filter-ts - (setf date-timestamps (cl-remove-if-not filter-ts date-timestamps))) - (--each date-timestamps - (push heading-string (gethash it ts-ht))))))) - (tss-sorted (-sort #'ts< (ht-keys ts-ht))) - (strings (cl-loop for ts in tss-sorted - collect (concat "\n" - (propertize (ts-format "%Y-%m-%d" ts) - 'face 'org-agenda-structure)) - append (ht-get ts-ht ts)))) - (org-ql-agenda--agenda nil nil :strings strings))) - - (org-ql-timeline* (org-agenda-files) - '(ts :from -14) - :filter-ts `(lambda (ts) - (ts<= ,(ts-adjust 'day -14 (ts-now)) ts))) -#+END_SRC - -Another, more up-to-date implementation: - -#+BEGIN_SRC elisp - ;; NOTE: ts structs don't (sometimes? or always?) compare properly - ;; with default hash tables, e.g. this code: - - ;; (let* ((ts-a #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572670800.0)) - ;; (ts-b #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572584400.0))) - ;; (list :equal (equal ts-a ts-b) - ;; :sxhash-equal (equal (sxhash ts-a) (sxhash ts-b)))) ;;=> (:equal nil :sxhash-equal t) - - ;; So we must use the "contents-hash" table as described in the Elisp manual. - (define-hash-table-test 'contents-hash 'equal 'sxhash-equal) - - (cl-defun org-ql-view-timeline (buffers-files &key from to on) - "FIXME: DOcstring" - (cl-flet ((parse-ts-arg - (arg type) - ;; Parse ARG as a string or TS struct and adjust it to the beginning - ;; or end of its day, depending on whether TYPE is `:begin' or `:end'. - (-let (((hour minute second) (cl-ecase type - (:begin '(0 0 0)) - (:end '(23 59 59))))) - (->> (cl-typecase arg - (string (ts-parse arg)) - (ts arg)) - (ts-apply :hour hour :minute minute :second second))))) - (let* ((ts-predicate `(lambda (ts) - ,(cond (on `(ts-in ,(parse-ts-arg on :begin) - ts - ,(parse-ts-arg on :end))) - ((and from to) `(ts-in ,(parse-ts-arg from :begin) - ts - ,(parse-ts-arg to :end))) - (from `(ts<= ,(parse-ts-arg from :begin) ts)) - (to `(ts<= ts ,(parse-ts-arg to :end))) - (t (user-error "Huh?"))))) - (query (cond (on `(ts :from ,(parse-ts-arg on :begin) - :to ,(parse-ts-arg on :end))) - (t (append (list 'ts) - (when from - `(:from ,(parse-ts-arg from :begin))) - (when to - `(:to ,(parse-ts-arg to :end))))))) - (date-ts-table (make-hash-table :test 'contents-hash)) - (_results (org-ql-select buffers-files query - :action (lambda () - (let* ((string (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-view--format-element))) - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both limit t) - for ts = (->> (match-string 0) ts-parse-org) - when (funcall ts-predicate ts) - do (cl-pushnew (cons ts (concat (ts-format " %H:%M" ts) - string)) - (gethash (ts-apply :hour 0 :minute 0 :second 0 ts) - date-ts-table) - :test #'equal)))))) - (date-tss-sorted (->> date-ts-table hash-table-keys (-sort #'ts<))) - (string (cl-loop for date-ts in date-tss-sorted - for date-string = (propertize (ts-format "%Y-%m-%d" date-ts) - 'face 'org-agenda-structure) - concat (concat "\n" date-string) - concat (cl-loop for (ts . entry) in (->> (gethash date-ts date-ts-table) - (-sort (-on #'ts< #'car))) - concat (concat "\n" entry))))) - (org-ql-view--display :buffer "Timeline" - :header "Timeline" - :string string)))) - - ;; Used like: - ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") -#+END_SRC - -[2019-09-26 Thu 21:28] Would probably make sense to implement this using the view-sections someday. - ** UNDERWAY [#B] "Node" caching [2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. @@ -598,49 +371,6 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC -** UNDERWAY [#B] Implement view with tabulated-list-mode or magit-section - -[2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. - -[2019-09-08 Sun 10:06] Came up with a prototype yesterday, in branch =wip/view-section=. Seems to work pretty well. - -One of the things in that branch is =org-ql-item=, which is a struct used to carry data for query results. It seems to work well. - -Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. - -*** MAYBE [#C] Experiment with =widget= - -The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. - -*** Code idea - -Inserting items into a view could look something like this: - -#+BEGIN_SRC elisp - (org-ql-view--insert-items - :header (ts-format "%Y-%m-%d" (ts-now)) - :items (org-ql-query - :select #'org-ql-current-item - :from (org-agenda-files) - :where '(or (deadline auto) - (scheduled :on today) - (ts-active :on today))) - :group-by '(org-ql-item-priority - org-ql-item-todo)) -#+END_SRC - -Items would be structs, and the =group-by= argument would be a list of accessors, like how =magit-todos= works. Arbitrary functions could also be passed to =group-by=, as whatever value the function returns is used to group them. =org-ql-current-item= would be a function that turns the result of =org-element-headline-parser= into the struct. - -Not sure if it should automatically add the number of items to the header, or if that should be done manually. - -*** Prior art - -**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] - -Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. - -**** magit-section - ** MAYBE [#C] Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. @@ -1249,6 +979,276 @@ For the query expression: [2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. +** PROJECT [#B] Recursive queries + +For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. + +This works pretty well. It needs polishing, and some refactoring so items can be indented completely (rather than leaving the keyword unindented, as it is now). + +#+BEGIN_SRC elisp + (cl-defun org-ql-agenda-recursive (buffers-or-files queries &key action narrow sort) + (cl-labels ((rec (queries element indent) + (org-with-point-at (org-element-property :org-marker element) + (when-let* ((results (progn + (org-narrow-to-subtree) + (org-ql-select (current-buffer) + (car queries) + :action 'element-with-markers + :narrow t + :sort sort)))) + ;; Indent entry for each level + (setf results (--map + (org-element-put-property it :raw-value + (concat (s-repeat (* 5 indent) " ") + (org-element-property :raw-value it))) + results)) + (cons it (if (cdr queries) + (--map (rec (cdr queries) it) + results) + results)))))) + (when-let* ((indent 0) + (results (org-ql-select buffers-or-files + (car queries) + :action 'element-with-markers + :narrow narrow + :sort sort))) + (->> (if (cdr queries) + (--map (rec (cdr queries) it (1+ indent)) + results) + results) + (-flatten-n (1- (length queries))) + -non-nil + (org-ql-agenda--agenda nil nil + :entries))))) + + (cl-defun org-ql-select-recursive (buffers-or-files queries &key action narrow sort) + (cl-labels ((rec (queries element indent) + (org-with-point-at (org-element-property :org-marker element) + (when-let* ((results (progn + (org-narrow-to-subtree) + (org-ql-select (current-buffer) + (car queries) + :action 'element-with-markers + :narrow t + :sort sort)))) + ;; Indent entry for each level + (setf results (--map + (org-element-put-property it :raw-value + (concat (s-repeat (* 5 indent) " ") + (org-element-property :raw-value it))) + results)) + (cons it (if (cdr queries) + (--map (rec (cdr queries) it) + results) + results)))))) + (when-let* ((indent 0) + (results (org-ql-select buffers-or-files + (car queries) + :action 'element-with-markers + :narrow narrow + :sort sort))) + (->> (if (cdr queries) + (--map (rec (cdr queries) it (1+ indent)) + results) + results) + (-flatten-n (1- (length queries))) + -non-nil)))) +#+END_SRC + +** PROJECT [#B] Timeline view +:PROPERTIES: +:ID: 00573552-ffe9-4608-8904-7f6c73246b6d +:END: + +e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: + +#+BEGIN_SRC elisp + (cl-defun org-ql-timeline (buffers-files query) + (let ((results + (org-ql-select buffers-files + query :action + (lambda () + (let* ((heading-string + (->> (org-element-headline-parser + (line-end-position)) + org-ql--add-markers + org-ql-agenda--format-element)) + (timestamps + (cl-loop with limit = (org-entry-end-position) + while (re-search-forward org-ts-regexp-both + limit t) + collect (ts-parse-org (match-string 0)))) + (timestamp-strings + (->> timestamps + (-sort #'ts<) + (--map (concat " " (ts-format it)))))) + (s-join "\n" (cons heading-string timestamp-strings)))) + :sort '(date)))) + (org-ql-agenda--agenda nil nil :strings results))) + + (org-ql-timeline (org-agenda-files) + '(and "Emacs" (ts))) + + ;; More timeline-like version, organized by date rather than task. + + (cl-defun org-ql-timeline* (buffers-files query &key filter-ts) + (let* ((ts-ht (ht)) + (results (org-ql-select buffers-files + query + :action (lambda () + (let* ((heading-string + (->> (org-element-headline-parser + (line-end-position)) + org-ql--add-markers + org-ql-agenda--format-element)) + (date-timestamps + ;; Each one set to 00:00:00. + (cl-loop with limit = (org-entry-end-position) + while (re-search-forward org-ts-regexp-both + limit t) + collect (->> (match-string 0) + ts-parse-org + (ts-apply :hour 0 :minute 0 :second 0))))) + (setf date-timestamps (delete-dups date-timestamps)) + (when filter-ts + (setf date-timestamps (cl-remove-if-not filter-ts date-timestamps))) + (--each date-timestamps + (push heading-string (gethash it ts-ht))))))) + (tss-sorted (-sort #'ts< (ht-keys ts-ht))) + (strings (cl-loop for ts in tss-sorted + collect (concat "\n" + (propertize (ts-format "%Y-%m-%d" ts) + 'face 'org-agenda-structure)) + append (ht-get ts-ht ts)))) + (org-ql-agenda--agenda nil nil :strings strings))) + + (org-ql-timeline* (org-agenda-files) + '(ts :from -14) + :filter-ts `(lambda (ts) + (ts<= ,(ts-adjust 'day -14 (ts-now)) ts))) +#+END_SRC + +Another, more up-to-date implementation: + +#+BEGIN_SRC elisp + ;; NOTE: ts structs don't (sometimes? or always?) compare properly + ;; with default hash tables, e.g. this code: + + ;; (let* ((ts-a #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572670800.0)) + ;; (ts-b #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572584400.0))) + ;; (list :equal (equal ts-a ts-b) + ;; :sxhash-equal (equal (sxhash ts-a) (sxhash ts-b)))) ;;=> (:equal nil :sxhash-equal t) + + ;; So we must use the "contents-hash" table as described in the Elisp manual. + (define-hash-table-test 'contents-hash 'equal 'sxhash-equal) + + (cl-defun org-ql-view-timeline (buffers-files &key from to on) + "FIXME: DOcstring" + (cl-flet ((parse-ts-arg + (arg type) + ;; Parse ARG as a string or TS struct and adjust it to the beginning + ;; or end of its day, depending on whether TYPE is `:begin' or `:end'. + (-let (((hour minute second) (cl-ecase type + (:begin '(0 0 0)) + (:end '(23 59 59))))) + (->> (cl-typecase arg + (string (ts-parse arg)) + (ts arg)) + (ts-apply :hour hour :minute minute :second second))))) + (let* ((ts-predicate `(lambda (ts) + ,(cond (on `(ts-in ,(parse-ts-arg on :begin) + ts + ,(parse-ts-arg on :end))) + ((and from to) `(ts-in ,(parse-ts-arg from :begin) + ts + ,(parse-ts-arg to :end))) + (from `(ts<= ,(parse-ts-arg from :begin) ts)) + (to `(ts<= ts ,(parse-ts-arg to :end))) + (t (user-error "Huh?"))))) + (query (cond (on `(ts :from ,(parse-ts-arg on :begin) + :to ,(parse-ts-arg on :end))) + (t (append (list 'ts) + (when from + `(:from ,(parse-ts-arg from :begin))) + (when to + `(:to ,(parse-ts-arg to :end))))))) + (date-ts-table (make-hash-table :test 'contents-hash)) + (_results (org-ql-select buffers-files query + :action (lambda () + (let* ((string (->> (org-element-headline-parser + (line-end-position)) + org-ql--add-markers + org-ql-view--format-element))) + (cl-loop with limit = (org-entry-end-position) + while (re-search-forward org-ts-regexp-both limit t) + for ts = (->> (match-string 0) ts-parse-org) + when (funcall ts-predicate ts) + do (cl-pushnew (cons ts (concat (ts-format " %H:%M" ts) + string)) + (gethash (ts-apply :hour 0 :minute 0 :second 0 ts) + date-ts-table) + :test #'equal)))))) + (date-tss-sorted (->> date-ts-table hash-table-keys (-sort #'ts<))) + (string (cl-loop for date-ts in date-tss-sorted + for date-string = (propertize (ts-format "%Y-%m-%d" date-ts) + 'face 'org-agenda-structure) + concat (concat "\n" date-string) + concat (cl-loop for (ts . entry) in (->> (gethash date-ts date-ts-table) + (-sort (-on #'ts< #'car))) + concat (concat "\n" entry))))) + (org-ql-view--display :buffer "Timeline" + :header "Timeline" + :string string)))) + + ;; Used like: + ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") +#+END_SRC + +[2019-09-26 Thu 21:28] Would probably make sense to implement this using the view-sections someday. + +** PROJECT [#B] Implement view with tabulated-list-mode or magit-section + +[2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. + +[2019-09-08 Sun 10:06] Came up with a prototype yesterday, in branch =wip/view-section=. Seems to work pretty well. + +One of the things in that branch is =org-ql-item=, which is a struct used to carry data for query results. It seems to work well. + +Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. + +*** MAYBE [#C] Experiment with =widget= + +The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. + +*** Code idea + +Inserting items into a view could look something like this: + +#+BEGIN_SRC elisp + (org-ql-view--insert-items + :header (ts-format "%Y-%m-%d" (ts-now)) + :items (org-ql-query + :select #'org-ql-current-item + :from (org-agenda-files) + :where '(or (deadline auto) + (scheduled :on today) + (ts-active :on today))) + :group-by '(org-ql-item-priority + org-ql-item-todo)) +#+END_SRC + +Items would be structs, and the =group-by= argument would be a list of accessors, like how =magit-todos= works. Arbitrary functions could also be passed to =group-by=, as whatever value the function returns is used to group them. =org-ql-current-item= would be a function that turns the result of =org-element-headline-parser= into the struct. + +Not sure if it should automatically add the number of items to the header, or if that should be done manually. + +*** Prior art + +**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] + +Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. + +**** magit-section + ** PROJECT Dynamic blocks *** TODO [#B] Save view to dynamic block From cd95d10f05f1d770c17b6d70534578a11a0357d2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 04:55:43 -0600 Subject: [PATCH 200/560] Add: Dynamic block (property) column --- README.org | 27 +++++++++-------- notes.org | 33 ++++++++++++-------- org-ql-search.el | 31 +++++++++++++------ org-ql.info | 78 ++++++++++++++++++++++++++---------------------- 4 files changed, 99 insertions(+), 70 deletions(-) diff --git a/README.org b/README.org index 6fcfc92..8794c33 100644 --- a/README.org +++ b/README.org @@ -404,29 +404,30 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience Org QL provides a dynamic block that lists entries in the current document matching a query. In the header, these parameters are supported: + ~:query~: An Org QL query expression in either sexp or non-sexp form. -+ ~:columns~ A list of columns, including ~heading~, ~todo~, ~priority~, ~deadline~, ~scheduled~. - - Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the priority column: ~(priority "P")~ ++ ~:columns~ A list of columns, including ~heading~, ~todo~, ~property~, ~priority~, ~deadline~, ~scheduled~. + - Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the priority column: ~(priority "P")~. + - For certain columns, like =property=, arguments may be passed by specifying the column type itself as a list. For example, to display a column showing the values of a ~property~ named ~milestone~, with the header being abbreviated to ~M~: ~((property "milestone") "M")~. + ~:sort~ One or a list of Org QL sorting methods (see ~org-ql-select~). + ~:take~ Optionally take a number of results from the front (a positive number) or the end (a negative number) of the results. + ~:ts-format~ Optional format string used to format timestamp-based columns. The heading column is formatted as a link to the heading (not shown in the following example). -For example, this dynamic block shows the first seven headings that are to-do items with priority A or B, sorted by deadline then priority, with certain columns and timestamp format: +For example, this dynamic block shows the first seven headings that are to-do items with priority A or B, sorted by deadline then priority, with certain columns (including the value of the =agenda-group= property with a custom header) and timestamp format: # NOTE: These results are edited manually because the Org links don't display well in the Info manual. #+BEGIN_SRC org - ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | P | Deadline | Heading | - |------+---+------------------+---------------------------------------| - | TODO | A | 2017-07-07 00:00 | Take over the world | - | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | - | TODO | A | 2017-07-15 00:00 | Take over the universe | - | TODO | B | 2017-07-21 00:00 | Internet | - | TODO | A | 2017-08-01 00:00 | Spaceship lease | - | TODO | A | | Skype with president of Antarctica | - | TODO | B | | Take over Mars | + ,#+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") ((property "agenda-group") "Group") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Group | Deadline | Heading | + |------+---+-------+------------------+---------------------------------------| + | TODO | A | | 2017-07-07 00:00 | Take over the world | + | TODO | B | | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | plans | 2017-07-15 00:00 | Take over the universe | + | TODO | B | | 2017-07-21 00:00 | Internet | + | TODO | A | bills | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | | Skype with president of Antarctica | + | TODO | B | | | Take over Mars | ,#+END: #+END_SRC diff --git a/notes.org b/notes.org index bbfa442..3718c69 100644 --- a/notes.org +++ b/notes.org @@ -24,12 +24,8 @@ | P | Keyword | Heading | |---+----------+--------------------------------------------------------------------| | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | -| B | UNDERWAY | [[Recursive queries][Recursive queries]] | -| B | UNDERWAY | [[Timeline view][Timeline view]] | | B | UNDERWAY | [["Node" caching]["Node" caching]] | -| B | UNDERWAY | [[Implement view with tabulated-list-mode or magit-section][Implement view with tabulated-list-mode or magit-section]] | | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | -| | UNDERWAY | [[Add automated tests][Add automated tests]] | #+END: ** To-do @@ -48,6 +44,16 @@ | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | #+END: +** Milestones + +[[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Milestones%2522][org-ql-search: Milestones]] + +#+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 +| M | P | Todo | Heading | +|-----+---+------+----------------------------| +| 0.6 | B | TODO | [[Save view to dynamic block][Save view to dynamic block]] | +#+END: + * [#A] Tasks :PROPERTIES: :TOC: :include descendants :depth 1 @@ -68,13 +74,9 @@ - [[#normalize-queries][Normalize queries]] - [[#update-view-screenshots][Update view screenshots]] - [[#org-agenda-skip-function][org-agenda-skip-function]] -- [[#test-caching][Test caching]] - [[#update-commentary][Update commentary]] - [[#outline-path-predicate][Outline path predicate]] -- [[#recursive-queries][Recursive queries]] -- [[#timeline-view][Timeline view]] - [[#node-caching]["Node" caching]] -- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] @@ -82,7 +84,11 @@ - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] +- [[#recursive-queries][Recursive queries]] +- [[#timeline-view][Timeline view]] +- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#dynamic-blocks][Dynamic blocks]] +- [[#test-caching][Test caching]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] - [[#byte-compile-lambdas][Byte-compile lambdas]] @@ -226,10 +232,6 @@ As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integra I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... -** TODO [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - ** TODO [#C] Update commentary ** UNDERWAY [#A] Outline path predicate @@ -1252,6 +1254,9 @@ Appears to be another implementation of magit-section-like expandable sections. ** PROJECT Dynamic blocks *** TODO [#B] Save view to dynamic block +:PROPERTIES: +:milestone: 0.6 +:END: [2020-11-12 Thu 03:23] A command to do this would be very helpful. @@ -1334,6 +1339,10 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this [2020-11-10 Tue 00:03] I think it's ready to merge now. +** PROJECT [#C] Test caching + +See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. diff --git a/org-ql-search.el b/org-ql-search.el index 3abc468..2c4b213 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -247,10 +247,17 @@ Valid parameters include: form. :columns A list of columns, including `heading', `todo', - `priority', `deadline', `scheduled'. Each column may - also be specified as a list with the second element - being a header string. For example, to abbreviate - the priority column: (priority \"P\") + `property', `priority', `deadline', `scheduled'. + Each column may also be specified as a list with the + second element being a header string. For example, + to abbreviate the priority column: (priority \"P\"). + For certain columns, like `property', arguments may + be passed by specifying the column type itself as a + list. For example, to display a column showing the + values of a property named \"milestone\", with the + header being abbreviated to \"M\": + + ((property \"milestone\") \"M\"). :sort One or a list of Org QL sorting methods (see `org-ql-select'). @@ -287,7 +294,9 @@ For example, an org-ql dynamic block header could look like: (ts-format ts-format (ts-parse-org-element it))))) (cons 'scheduled (lambda (element) (--when-let (org-element-property :scheduled element) - (ts-format ts-format (ts-parse-org-element it))))))) + (ts-format ts-format (ts-parse-org-element it))))) + (cons 'property (lambda (element property &optional value) + (org-element-property (intern (concat ":" (upcase property))) element))))) (elements (org-ql-query :from (current-buffer) :where query :select '(org-element-headline-parser (line-end-position)) @@ -298,10 +307,14 @@ For example, an org-ql dynamic block header could look like: (integer (-take take elements))))) (cl-labels ((format-element (element) (string-join (cl-loop for column in columns - for fn = (cl-etypecase column - (symbol (alist-get column format-fns)) - (list (alist-get (car column) format-fns))) - collect (or (funcall fn element) "")) + collect (or (pcase-exhaustive column + ((pred symbolp) + (funcall (alist-get column format-fns) element)) + (`((,column . ,args) ,header) + (apply (alist-get column format-fns) element args)) + (`(,column ,header) + (funcall (alist-get column format-fns) element))) + "")) " | "))) ;; Table header (insert "| " (string-join (--map (pcase it diff --git a/org-ql.info b/org-ql.info index 3d86d66..9739c60 100644 --- a/org-ql.info +++ b/org-ql.info @@ -730,10 +730,15 @@ supported: • ‘:query’: An Org QL query expression in either sexp or non-sexp form. • ‘:columns’ A list of columns, including ‘heading’, ‘todo’, - ‘priority’, ‘deadline’, ‘scheduled’. + ‘property’, ‘priority’, ‘deadline’, ‘scheduled’. • Each column may also be specified as a list with the second element being a header string. For example, to abbreviate the - priority column: ‘(priority "P")’ + priority column: ‘(priority "P")’. + • For certain columns, like property, arguments may be passed by + specifying the column type itself as a list. For example, to + display a column showing the values of a ‘property’ named + ‘milestone’, with the header being abbreviated to ‘M’: + ‘((property "milestone") "M")’. • ‘:sort’ One or a list of Org QL sorting methods (see ‘org-ql-select’). • ‘:take’ Optionally take a number of results from the front (a @@ -746,18 +751,19 @@ in the following example). For example, this dynamic block shows the first seven headings that are to-do items with priority A or B, sorted by deadline then priority, -with certain columns and timestamp format: +with certain columns (including the value of the agenda-group property +with a custom header) and timestamp format: - #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" - | Todo | P | Deadline | Heading | - |------+---+------------------+---------------------------------------| - | TODO | A | 2017-07-07 00:00 | Take over the world | - | TODO | B | 2017-07-10 00:00 | Renew membership in supervillain club | - | TODO | A | 2017-07-15 00:00 | Take over the universe | - | TODO | B | 2017-07-21 00:00 | Internet | - | TODO | A | 2017-08-01 00:00 | Spaceship lease | - | TODO | A | | Skype with president of Antarctica | - | TODO | B | | Take over Mars | + #+BEGIN: org-ql :query "todo: priority:A,B" :columns (todo (priority "P") ((property "agenda-group") "Group") deadline heading) :sort (deadline priority) :take 7 :ts-format "%Y-%m-%d %H:%M" + | Todo | P | Group | Deadline | Heading | + |------+---+-------+------------------+---------------------------------------| + | TODO | A | | 2017-07-07 00:00 | Take over the world | + | TODO | B | | 2017-07-10 00:00 | Renew membership in supervillain club | + | TODO | A | plans | 2017-07-15 00:00 | Take over the universe | + | TODO | B | | 2017-07-21 00:00 | Internet | + | TODO | A | bills | 2017-08-01 00:00 | Spaceship lease | + | TODO | A | | | Skype with president of Antarctica | + | TODO | B | | | Take over Mars | #+END:  @@ -1289,29 +1295,29 @@ Node: Functions / Macros19755 Node: Agenda-like views20010 Node: Listing / acting-on results21415 Node: Dynamic block26017 -Node: Links28180 -Node: Tips28867 -Node: Changelog29185 -Node: 05-pre29824 -Node: 04631063 -Node: 04531466 -Node: 04431825 -Node: 04332182 -Node: 04232377 -Node: 04132536 -Node: 0432775 -Node: 03236706 -Node: 03137083 -Node: 0337280 -Node: 02340255 -Node: 02240483 -Node: 02140751 -Node: 0240950 -Node: 0144985 -Node: Notes45086 -Node: Comparison with Org Agenda searches45248 -Node: org-sidebar46120 -Node: License46399 +Node: Links28715 +Node: Tips29402 +Node: Changelog29720 +Node: 05-pre30359 +Node: 04631598 +Node: 04532001 +Node: 04432360 +Node: 04332717 +Node: 04232912 +Node: 04133071 +Node: 0433310 +Node: 03237241 +Node: 03137618 +Node: 0337815 +Node: 02340790 +Node: 02241018 +Node: 02141286 +Node: 0241485 +Node: 0145520 +Node: Notes45621 +Node: Comparison with Org Agenda searches45783 +Node: org-sidebar46655 +Node: License46934  End Tag Table From 56647d4b1159f3dc3e638ea2e7b1a85446884ca5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 12 Nov 2020 05:23:59 -0600 Subject: [PATCH 201/560] Notes: Update --- notes.org | 99 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 40 deletions(-) diff --git a/notes.org b/notes.org index 3718c69..586045f 100644 --- a/notes.org +++ b/notes.org @@ -30,7 +30,7 @@ ** To-do -[[org-ql-search:todo:?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529][org-ql-search: Tasks]] ++ [[org-ql-search:todo:?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529][org-ql-search: Tasks]] #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 | P | Todo | Heading | @@ -44,6 +44,20 @@ | A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | #+END: +** [[org-ql-search:(and%20(todo%20"PROJECT")%20(not%20(descendants%20(todo%20"NEXT"))))?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529&title=%2522Stuck%2520Projects%2522][Stuck projects]] + +#+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns ((priority "P") heading) :sort (priority date) :take 7 +| P | Heading | +|---+---------------------------------------------------| +| A | [[Outline path predicate][Outline path predicate]] | +| A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| A | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | +| A | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | +| A | [[Group tag support][Group tag support]] | +| A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| B | [[Recursive queries][Recursive queries]] | +#+END: + ** Milestones [[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Milestones%2522][org-ql-search: Milestones]] @@ -63,7 +77,6 @@ - [[#document-sorters][Document sorters]] - [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] -- [[#save-views-to-dynamic-blocks][Save views to dynamic blocks]] - [[#consider-how-to-secure-searches-from-links-and-dynamic-blocks][Consider how to "secure" searches from links and dynamic blocks]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] - [[#add-more-sorters][Add more sorters?]] @@ -75,11 +88,12 @@ - [[#update-view-screenshots][Update view screenshots]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] -- [[#outline-path-predicate][Outline path predicate]] +- [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#node-caching]["Node" caching]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#outline-path-predicate][Outline path predicate]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] @@ -96,6 +110,7 @@ - [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] - [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] - [[#use-macros-for-date][Use macros for date]] +- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] :END: ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate @@ -114,10 +129,6 @@ Note that the built-in sorting only works on Org elements, which is the default For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. -** TODO [#A] Save views to dynamic blocks - -[2020-11-10 Tue 04:31] A command would save users from having to write out the dynamic block manually. - ** TODO [#A] Consider how to "secure" searches from links and dynamic blocks Theoretically one could put a sexp-based query into a link that would run arbitrary code to do something evil. Like: @@ -234,40 +245,11 @@ I should benchmark it to see how much difference it makes, because all those ~fs ** TODO [#C] Update commentary -** UNDERWAY [#A] Outline path predicate +** NEXT [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: +** NEXT [#A] Make dynamic blocks warn about sexp queries -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. +[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. ** UNDERWAY [#B] "Node" caching @@ -390,6 +372,41 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** PROJECT [#A] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. + ** PROJECT [#A] Convert simple sexp queries to non-sexp [2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... @@ -1258,7 +1275,9 @@ Appears to be another implementation of magit-section-like expandable sections. :milestone: 0.6 :END: -[2020-11-12 Thu 03:23] A command to do this would be very helpful. +[2020-11-10 Tue 04:31] A command would save users from having to write out the dynamic block manually. + +[2020-11-12 Thu 03:23] A command to do this would be very helpful. (Yes, I entered this idea twice. I should use my own systems better, apparently. But that's what this package is all about, right?) *** DONE [#A] Implement dynamic blocks From b90e6e25d0df92771e7f36ce8a4f39fad5d5cad8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 13 Nov 2020 02:42:52 -0600 Subject: [PATCH 202/560] Tests: Use test buffer for link safety tests --- tests/test-org-ql.el | 144 +++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 68 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index d31a08f..95519e8 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1172,79 +1172,87 @@ RESULTS should be a list of strings as returned by (require 'org-ql-search) (require 'org-ql-view) - (cl-flet ((open-link - (link) (with-temp-buffer - (org-mode) - (insert link) - (backward-char 1) - (call-interactively #'org-open-at-point)))) + ;; The :auto-map test requires there to be results (because the org-super-agenda :auto-map group's + ;; key-form, where the safety check is, only gets evaluated when there are results). Using + ;; `with-temp-buffer' in the `open-link' function causes the temp buffer to be killed before the results + ;; have a chance to be gathered. So we make a test buffer and run the test in that, with a test heading. - (it "buffers-files parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (quoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]]") - (unquoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]]")) - (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) - (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) - (expect (open-link quoted-lambda-in-list-link) - :to-throw 'wrong-type-argument '(stringp ((quote (lambda nil (message "AHA")))))) - (expect (open-link unquoted-lambda-in-list-link) - :to-throw 'wrong-type-argument '(stringp ((lambda nil (message "AHA"))))))) + (let ((test-buffer (get-buffer-create "*test-org-ql*"))) + (cl-flet ((open-link + (link) (with-current-buffer test-buffer + (erase-buffer) + (org-mode) + (insert "* TODO Test heading \n\n") + (insert link) + (backward-char 1) + (call-interactively #'org-open-at-point)))) - (it "super-groups parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (quoted-expression-link "[[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]]") - (unquoted-expression-link "[[org-ql-search:todo:?super-groups%3D%22AHA%22]]") - (pred-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]") - (auto-map-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]")) - (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(listp lambda)) - (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(listp lambda)) - (expect (open-link quoted-expression-link) - :to-throw 'wrong-type-argument '(listp message)) - (expect (open-link unquoted-expression-link) - :to-throw 'error '("cl-etypecase failed: AHA, (symbol list)")) + (it "buffers-files parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'wrong-type-argument '(stringp ((quote (lambda nil (message "AHA")))))) + (expect (open-link unquoted-lambda-in-list-link) + :to-throw 'wrong-type-argument '(stringp ((lambda nil (message "AHA"))))))) - ;; FIXME: These two tests will not pass (i.e. they will not - ;; signal an error) until the version of org-super-agenda in - ;; the test sandbox is upgraded, which I'll do when MELPA - ;; packages the latest version. On the bright side, I just - ;; confirmed that, without the fix to org-super-agenda, - ;; these are vulnerable, which means that the test catches - ;; this problem and detects the fix. - (expect (open-link pred-selector-link) - :to-throw 'error '("Unsafe groups disallowed (:pred): (lambda (_) (message AHA))")) - (expect (open-link auto-map-selector-link) - :to-throw 'error '("Unsafe groups disallowed (:auto-map): ((lambda (_) (message AHA)))")))) + (it "super-groups parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") + (quoted-expression-link "[[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]]") + (unquoted-expression-link "[[org-ql-search:todo:?super-groups%3D%22AHA%22]]") + (pred-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]") + (auto-map-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(listp lambda)) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(listp lambda)) + (expect (open-link quoted-expression-link) + :to-throw 'wrong-type-argument '(listp message)) + (expect (open-link unquoted-expression-link) + :to-throw 'error '("cl-etypecase failed: AHA, (symbol list)")) - (it "title parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (expression-link "[[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]]")) - (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(characterp lambda)) - (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(characterp lambda)) - (expect (open-link expression-link) - :to-throw 'wrong-type-argument '(characterp message)))) + ;; FIXME: These two tests will not pass (i.e. they will not + ;; signal an error) until the version of org-super-agenda in + ;; the test sandbox is upgraded, which I'll do when MELPA + ;; packages the latest version. On the bright side, I just + ;; confirmed that, without the fix to org-super-agenda, + ;; these are vulnerable, which means that the test catches + ;; this problem and detects the fix. + (expect (open-link pred-selector-link) + :to-throw 'error '("Unsafe groups disallowed (:pred): (lambda (_) (message AHA))")) + (expect (open-link auto-map-selector-link) + :to-throw 'error '("Unsafe groups disallowed (:auto-map): ((lambda (_) (message AHA)))")))) - (it "sort parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (quoted-lambda-in-list-link "[[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]]") - (unquoted-lambda-in-list-link "[[org-ql-search:todo:?sort=((lambda%20nil%20(message%20\"AHA\")))]]")) - (expect (open-link quoted-lambda-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) - (expect (open-link unquoted-lambda-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) - (expect (open-link quoted-lambda-in-list-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((quote (lambda (_ _) (message AHA))))). Link not opened")) - (expect (open-link unquoted-lambda-in-list-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((lambda nil (message AHA)))). Link not opened"))))))) + (it "title parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (expression-link "[[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'wrong-type-argument '(characterp lambda)) + (expect (open-link unquoted-lambda-link) + :to-throw 'wrong-type-argument '(characterp lambda)) + (expect (open-link expression-link) + :to-throw 'wrong-type-argument '(characterp message)))) + + (it "sort parameter" + (let ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?sort=((lambda%20nil%20(message%20\"AHA\")))]]")) + (expect (open-link quoted-lambda-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + (expect (open-link unquoted-lambda-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((quote (lambda (_ _) (message AHA))))). Link not opened")) + (expect (open-link unquoted-lambda-in-list-link) + :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((lambda nil (message AHA)))). Link not opened")))))))) ;; Local Variables: ;; truncate-lines: t From f8b41ea0273cca8d72e4e0a40a6c9bd0671302bd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 13 Nov 2020 02:44:46 -0600 Subject: [PATCH 203/560] Fix: (org-dblock-write:org-ql) Remove unused argument --- org-ql-search.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index 2c4b213..a5f9b7b 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -295,7 +295,7 @@ For example, an org-ql dynamic block header could look like: (cons 'scheduled (lambda (element) (--when-let (org-element-property :scheduled element) (ts-format ts-format (ts-parse-org-element it))))) - (cons 'property (lambda (element property &optional value) + (cons 'property (lambda (element property) (org-element-property (intern (concat ":" (upcase property))) element))))) (elements (org-ql-query :from (current-buffer) :where query From 51f987c6b82934b66057513b26e49ccb59343424 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 13 Nov 2020 02:45:45 -0600 Subject: [PATCH 204/560] Fix: (org-dblock-write:org-ql) Rename unused variables --- org-ql-search.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index a5f9b7b..59d57d5 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -310,9 +310,9 @@ For example, an org-ql dynamic block header could look like: collect (or (pcase-exhaustive column ((pred symbolp) (funcall (alist-get column format-fns) element)) - (`((,column . ,args) ,header) + (`((,column . ,args) ,_header) (apply (alist-get column format-fns) element args)) - (`(,column ,header) + (`(,column ,_header) (funcall (alist-get column format-fns) element))) "")) " | "))) From be4e941fc9d0efbfaff3bee90aa9a791b0e194fa Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 13 Nov 2020 03:13:48 -0600 Subject: [PATCH 205/560] Notes: Update --- notes.org | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/notes.org b/notes.org index 586045f..f883349 100644 --- a/notes.org +++ b/notes.org @@ -89,10 +89,12 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] +- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#node-caching]["Node" caching]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#fix-org-ql-view--link-open-on-newer-org-versions][Fix org-ql-view--link-open on newer Org versions]] - [[#outline-path-predicate][Outline path predicate]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] @@ -110,7 +112,6 @@ - [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] - [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] - [[#use-macros-for-date][Use macros for date]] -- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] :END: ** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate @@ -372,6 +373,21 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** PROJECT [#A] Fix =org-ql-view--link-open= on newer Org versions +:PROPERTIES: +:milestone: 0.5 +:END: + +The version of Org in my personal that passes a URL-decoded string (i.e. as if run through =url-unhex-string=) as the argument to =org-ql-view--link-open=. But Org 9.3 in Emacs 27.1 passes a non-URL-decoded string, so =org-ql-view--link-open= needs to pass it through =url-unhex-string= itself. + +But I don't know which version of Org that changed in. I'm comparing the function =org-open-at-point=, but it's a 114-line function, and in neither version does it call =url-unhex-string=, so whatever code decodes the string must be elsewhere. + +I do recall something about links changing in Org 9.3 (or thereabouts), so that was probably part of it. Maybe I can find it in the release notes. I just need to know basically which version it happened in. + +I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. + +*** NEXT [#A] Check Org release notes for link changes + ** PROJECT [#A] Outline path predicate [2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: From dd30f07942650fb1e058ac42eb78d880255246a0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 05:22:59 -0600 Subject: [PATCH 206/560] Notes: Update --- notes.org | 445 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 271 insertions(+), 174 deletions(-) diff --git a/notes.org b/notes.org index f883349..f0f0c59 100644 --- a/notes.org +++ b/notes.org @@ -1,4 +1,5 @@ #+PROPERTY: LOGGING nil +#+TODO: TODO MAYBE NEXT PROJECT UNDERWAY WAITING | DONE CANCELED * [#A] Contents :PROPERTIES: @@ -16,56 +17,66 @@ * [#A] Overview +** Bugs + ++ [[org-ql-search:todo%3A%20tags%3Abug?super-groups=%28%28%3Aauto-property%20%22Milestone%22%29%29&sort=%28priority%29&title=%22Bugs%22][org-ql-search: Bugs]] + +#+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +| P | M | Keyword | Heading | +|---+---+---------+---------------------------------------------------------------------| +| A | | NEXT | [[Fix query-sexp-to-string function's handling of, e.g. =descendants=][Fix query-sexp-to-string function's handling of, e.g. =descendants=]] | +#+END: + ** Underway -[[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] ++ [[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] #+BEGIN: org-ql :query (todo "UNDERWAY") :columns ((priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" | P | Keyword | Heading | |---+----------+--------------------------------------------------------------------| -| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | | B | UNDERWAY | [["Node" caching]["Node" caching]] | | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | #+END: ** To-do -+ [[org-ql-search:todo:?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529][org-ql-search: Tasks]] ++ [[org-ql-search:todo%3A?super-groups=%28%28%3Atodo%20%22NEXT%22%29%20%28%3Atodo%20%22PROJECT%22%29%20%28%3Aauto-priority%29%29&sort=%28todo%29][org-ql-search: Tasks]] #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 -| P | Todo | Heading | -|---+----------+-----------------------------------------------------------------| -| A | TODO | [[Add ~:auto~ keyword to ~(planning)~ predicate][Add ~:auto~ keyword to ~(planning)~ predicate]] | -| A | TODO | [[Document sorters][Document sorters]] | -| A | TODO | [[Org block to insert results of queries with links to entries][Org block to insert results of queries with links to entries]] | -| A | TODO | [[Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~][Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~]] | -| A | TODO | [[Save views to dynamic blocks][Save views to dynamic blocks]] | -| A | TODO | [[Consider how to "secure" searches from links and dynamic blocks][Consider how to "secure" searches from links and dynamic blocks]] | -| A | UNDERWAY | [[Outline path predicate][Outline path predicate]] | +| P | Todo | Heading | +|---+---------+----------------------------------------------------------------------------| +| A | NEXT | [[Fix query-sexp-to-string function's handling of, e.g. =descendants=][Fix query-sexp-to-string function's handling of, e.g. =descendants=]] | +| A | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | +| A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| A | PROJECT | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | +| A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| A | PROJECT | [[Org link types [2/3\]][Org link types [2/3]​]] | #+END: -** [[org-ql-search:(and%20(todo%20"PROJECT")%20(not%20(descendants%20(todo%20"NEXT"))))?super-groups=%2528%2528%253Aauto-outline-path%2529%2529&sort=%2528priority%2529&title=%2522Stuck%2520Projects%2522][Stuck projects]] +** [[org-ql-search:%28and%20%28todo%20%22PROJECT%22%29%20%28not%20%28descendants%20%28todo%20%22NEXT%22%29%29%29%29?super-groups=%28%28%3Aauto-parent%29%29&sort=%28priority%29&title=%22Stuck%20Projects%22][org-ql-search: Stuck Projects]] #+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns ((priority "P") heading) :sort (priority date) :take 7 -| P | Heading | -|---+---------------------------------------------------| -| A | [[Outline path predicate][Outline path predicate]] | -| A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| A | [[Tools%20for%20saving%20queries%20and%20accessing%20them%20%5B3/4%5D][Tools for saving queries and accessing them {3/4}]] | -| A | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | -| A | [[Group tag support][Group tag support]] | -| A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| B | [[Recursive queries][Recursive queries]] | +| P | Heading | +|---+----------------------------------------------------------------------------| +| A | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| A | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | +| A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| A | [[Org link types [2/3\]][Org link types [2/3]​]] | +| B | [[Outline path predicate][Outline path predicate]] | +| B | [[Group tag support][Group tag support]] | #+END: ** Milestones -[[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Milestones%2522][org-ql-search: Milestones]] +[[org-ql-search:todo%3A?super-groups=%28%28%3Aauto-property%20%22milestone%22%29%29&sort=%28todo%29&title=%22Milestones%22][org-ql-search: Milestones]] #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|-----+---+------+----------------------------| -| 0.6 | B | TODO | [[Save view to dynamic block][Save view to dynamic block]] | +| M | P | Todo | Heading | +|-----+---+---------+----------------------------------------------------------------------------| +| 0.5 | A | PROJECT | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | +| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | #+END: * [#A] Tasks @@ -74,18 +85,12 @@ :END: :CONTENTS: - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] -- [[#document-sorters][Document sorters]] -- [[#org-block-to-insert-results-of-queries-with-links-to-entries][Org block to insert results of queries with links to entries]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] -- [[#consider-how-to-secure-searches-from-links-and-dynamic-blocks][Consider how to "secure" searches from links and dynamic blocks]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] - [[#add-more-sorters][Add more sorters?]] - [[#default-sort][Default sort]] - [[#partial-match-for-property-queries][Partial match for property queries]] - [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] -- [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] -- [[#normalize-queries][Normalize queries]] -- [[#update-view-screenshots][Update view screenshots]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] @@ -94,16 +99,21 @@ - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] - [[#fix-org-ql-view--link-open-on-newer-org-versions][Fix org-ql-view--link-open on newer Org versions]] -- [[#outline-path-predicate][Outline path predicate]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] -- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] -- [[#group-tag-support][Group tag support]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] +- [[#outline-path-predicate][Outline path predicate]] +- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them [3/4]​]] +- [[#group-tag-support][Group tag support]] +- [[#document-the-sorting-functions][Document the sorting functions]] - [[#recursive-queries][Recursive queries]] - [[#timeline-view][Timeline view]] - [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] - [[#dynamic-blocks][Dynamic blocks]] +- [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] +- [[#normalize-queries][Normalize queries]] +- [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] @@ -114,32 +124,14 @@ - [[#use-macros-for-date][Use macros for date]] :END: -** TODO [#A] Add ~:auto~ keyword to ~(planning)~ predicate +** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. -** TODO [#A] Document sorters - -Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. - -** TODO [#A] Org block to insert results of queries with links to entries - -[2020-01-16 Thu 06:20] This idea just came to me when I was thinking about using the search-based paradigm vs. outline-based. This would allow both, e.g. some kind of =#+BEGIN_QUERY= block that would update when =C-c C-c= is pressed on it. - -** TODO [#A] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ +** TODO [#B] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. -** TODO [#A] Consider how to "secure" searches from links and dynamic blocks - -Theoretically one could put a sexp-based query into a link that would run arbitrary code to do something evil. Like: - -[[org-ql-search:(message "AHA")]] - -That's very unlikely to be abused, but it would be good to protect against it. Two possibilities: - -1. For sexp-based queries in links and dynamic blocks, prompt for confirmation before running. -2. Use a special variable to control whether lambdas and arbitrary sexps are allowed in queries, and disable it for links and dynamic blocks. (That might be difficult to do, since they could be buried in an ~and~ or something. A whitelist approach might be needed.) ** TODO [#B] Outline path in buffers-files arg :PROPERTIES: @@ -184,23 +176,6 @@ Searching that with a query like =property:author=Fabrice= returns nothing; the [2020-11-12 Thu 03:17] Will probably have to merge or delete some WIP branches first, otherwise they'll probably get conflicts. -** TODO [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] - -[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. - -** TODO [#C] Normalize queries - -[2019-07-16 Tue 11:49] This serves two purposes: - -1. Equivalent queries will return the same results from the cache. -2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file. - -So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. - -** TODO [#C] Update view screenshots - -e.g. doesn't currently show the =View= header. - ** TODO [#C] ~org-agenda-skip-function~ As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: @@ -247,6 +222,9 @@ I should benchmark it to see how much difference it makes, because all those ~fs ** TODO [#C] Update commentary ** NEXT [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: +:PROPERTIES: +:milestone: 0.5 +:END: ** NEXT [#A] Make dynamic blocks warn about sexp queries @@ -373,7 +351,27 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. -** PROJECT [#A] Fix =org-ql-view--link-open= on newer Org versions +** PROJECT [#A] Compatibility with Org 9.4 custom link changes :bug: +:PROPERTIES: +:milestone: 0.5 +:END: + +[2020-11-13 Fri 22:36] From [[https://www.orgmode.org/Changes.html][the changelog]]: + +#+BEGIN_QUOTE +Calling conventions changes when opening or exporting custom links + +This changes affects export back-ends, and libraries providing new link types. + +Function used in :follow link parameter is required to accept a second argument. Likewise, function used in :export parameter needs to accept a fourth argument. See org-link-set-parameters for details. + +Eventually, the function org-export-custom-protocol-maybe is now called with a fourth argument. Even though the 3-arguments definition is still supported, at least for now, we encourage back-end developers to switch to the new signature. +#+END_QUOTE + +Unfortunately it does not say what the new, required second argument is. + + +** PROJECT [#A] Fix =org-ql-view--link-open= on newer Org versions :compatibility:bug: :PROPERTIES: :milestone: 0.5 :END: @@ -386,42 +384,62 @@ I do recall something about links changing in Org 9.3 (or thereabouts), so that I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. -*** NEXT [#A] Check Org release notes for link changes +*** DONE [#A] Check Org release notes for link changes -** PROJECT [#A] Outline path predicate +[2020-11-13 Fri 22:44] From [[https://www.orgmode.org/Changes_old.html][the changelog]]: -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: +#+BEGIN_QUOTE +Change bracket link escaping syntax -#+BEGIN_SRC org - ,* Food +Org used to percent-encode sensitive characters in the URI part of the bracket links. - ,** Fruits +Now, escaping mechanism uses the usual backslash character, according to the following rules, applied in order: - ,*** Blueberries +- All consecutive \ characters at the end of the link must be escaped; +- Any ] character at the very end of the link must be escaped; +- All consecutive \ characters preceding ][ or ]] patterns must be escaped; +- Any ] character followed by either [ or ] must be escaped; +- Others ] and \ characters need not be escaped. - ,*** Grapes +When in doubt, use the function org-link-escape in order to turn a link string into its properly escaped form. - ,** Vegetables +The following function will help switching your links to the new syntax: - ,*** Carrots +(defun org-update-link-syntax (&optional no-query) + "Update syntax for links in current buffer. +Query before replacing a link, unless optional argument NO-QUERY +is non-nil." + (interactive "P") + (org-with-point-at 1 + (let ((case-fold-search t)) + (while (re-search-forward "\\[\\[[^]]*?%\\(?:2[05]\\|5[BD]\\)" nil t) + (let ((object (save-match-data (org-element-context)))) + (when (and (eq 'link (org-element-type object)) + (= (match-beginning 0) + (org-element-property :begin object))) + (goto-char (org-element-property :end object)) + (let* ((uri-start (+ 2 (match-beginning 0))) + (uri-end (save-excursion + (goto-char uri-start) + (re-search-forward "\\][][]" nil t) + (match-beginning 0))) + (uri (buffer-substring-no-properties uri-start uri-end))) + (when (or no-query + (y-or-n-p + (format "Possibly obsolete URI syntax: %S. Fix? " + uri))) + (setf (buffer-substring uri-start uri-end) + (org-link-escape (org-link-decode uri))))))))))) - ,*** Potatoes -#+END_SRC +The old org-link-escape and org-link-unescape functions have been renamed into org-link-encode and org-link-decode. +#+END_QUOTE -Matching could work like this: +This is exactly the kind of breaking, backwards-incompatible change that I've said should mandate a major-version increment. It's not only a change in Org's code, and a change that affects third-party packages, but it's a change in the file format! -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. +Is it even possible to support both Org 9.3+ and earlier versions at the same time? -Matching at a specific path would be something like: +This change doesn't even seem to make sense to me. Percent-encoding solves so many problems in a simple way: pass a string to the encoding function on the way in, and to the decoding function on the way out. Now, instead of a simple, standard way of encoding links, there's a list of Org-specific rules and Org-specific encoding/decoding functions. What is gained this way? -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. ** PROJECT [#A] Convert simple sexp queries to non-sexp @@ -525,7 +543,132 @@ To implement this with good performance probably needs an outline-path cache. I Maybe make it an option to automatically convert them when possible, because if a user wanted to add complexity to a string query, he'd have to rewrite it as a sexp. -** PROJECT [#A] Tools for saving queries and accessing them [3/4] +** PROJECT [#A] Checking links for unsafe parameters +:PROPERTIES: +:ID: ba70e375-eddb-40df-8892-fb418c1f70d1 +:END: +:LOGBOOK: +- State "PROJECT" from "UNDERWAY" [2020-11-12 Thu 00:26] +- State "UNDERWAY" from [2020-11-11 Wed 23:09] +:END: + +Theoretically one could put a sexp-based query into a link that would run arbitrary code to do something evil. Like: + +[[org-ql-search:(message "AHA")]] + +That's very unlikely to be abused, but it would be good to protect against it. Two possibilities: + +1. For sexp-based queries in links and dynamic blocks, prompt for confirmation before running. +2. Use a special variable to control whether lambdas and arbitrary sexps are allowed in queries, and disable it for links and dynamic blocks. (That might be difficult to do, since they could be buried in an ~and~ or something. A whitelist approach might be needed.) + +*** TODO [#A] Tag org-super-agenda 1.2 and bump required version in org-ql +:PROPERTIES: +:milestone: 0.5 +:END: + +That /should/ force the version of org-super-agenda with the fix to be installed when org-ql is upgraded. + +*** DONE Add automated tests +:LOGBOOK: +- State "UNDERWAY" from "TODO" [2020-11-12 Thu 00:24] +- State "TODO" from "MAYBE" [2020-11-11 Wed 23:16] +- State "MAYBE" from [2020-11-11 Wed 23:15] +:END: + +Maybe impractical, but maybe we could at least test that potentially unsafe ones signal errors. + +[2020-11-12 Thu 00:24] Works better than I expected. All the tests seem to correctly pass, signaling the correct errors for the correct reasons--except for the tests specific to org-super-agenda. For that, I'm currently waiting for MELPA to build the version of org-super-agenda that has the fix applied, so I can install that into the test sandbox, and then those two tests should pass also. + +*** DONE Enumerate and test parameters and potentially unsafe types +CLOSED: [2020-11-11 Wed 23:26] +:LOGBOOK: +- State "DONE" from "UNDERWAY" [2020-11-11 Wed 23:26] +- State "UNDERWAY" from [2020-11-11 Wed 23:15] +:END: + +#+CAPTION: Template for making testable links +#+BEGIN_SRC org +[[org-ql-search:todo:?]] +#+END_SRC + +#+CAPTION: Expression to insert encoded values into template (after the =?=) +#+BEGIN_SRC elisp + (insert (url-hexify-string (concat "buffers-files=" (prin1-to-string '((lambda () (message "AHA"))))))) +#+END_SRC + ++ [X] Buffers-Files: Expanded by =org-ql-view--expand-buffers-files=: + - [X] Quoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Quoted lambda in list (safe): [[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]] + - [X] Unquoted lambda in list: (safe) [[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]] ++ [X] Groups + - [X] Quoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] + - [X] Quoted expression (safe): [[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]] + - [X] Unquoted expression (safe): [[org-ql-search:todo:?super-groups%3D%22AHA%22]] + - [X] ~:pred~ selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] + - [X] =:auto-map= selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] ++ [X] Title + - [X] Quoted lambda (produces the same encoded value as unquoted lambda): (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Expression: (safe) [[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]] ++ [X] Sort + - [X] Bare, quoted lambda: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Bare, unquoted lambda: (UNSAFE, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] + - [X] Quoted lambda in list: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]] + - [X] Unquoted lambda in a list: (UNSAFE, but caught now): [[org-ql-search:todo:?sort=((lambda%20nil%20(message%20"AHA")))]] + +For the query expression: + +1. String queries are parsed by the PEG parsing function (which I will probably rename soon), which should only allow known Org QL predicates, not arbitrary functions. For example: + + #+BEGIN_SRC elisp + (org-ql--plain-query "message:AHA") ;;=> (regexp "message:AHA") + (org-ql--plain-query '(message "AHA")) ;;=> (wrong-type-argument stringp (message "AHA")) + (org-ql--plain-query "(message \"AHA\"") ;;=> (and (regexp "(message") (regexp "AHA")) + #+END_SRC + +2. Sexp queries already prompt for confirmation, unless the user has set =org-ql-view-ask-unsafe-links= to nil. + +[2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. + + +** PROJECT [#B] Outline path predicate + +[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: + +#+BEGIN_SRC org + ,* Food + + ,** Fruits + + ,*** Blueberries + + ,*** Grapes + + ,** Vegetables + + ,*** Carrots + + ,*** Potatoes +#+END_SRC + +Matching could work like this: + ++ ~(outline "Food")~ :: Would return all nodes. ++ ~(outline "Fruits")~ :: Would return all fruits. + +Matching at a specific path would be something like: + ++ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. + +I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. + +To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. + +[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. + +** PROJECT Tools for saving queries and accessing them [3/4] + Added example to =examples.org=. @@ -685,7 +828,7 @@ That seems to work, like: *** DONE Save query from ql-agenda buffer -** PROJECT [#A] Group tag support +** PROJECT [#B] Group tag support *** UNDERWAY Benchmarking tags searches without and with new group-tags support @@ -937,82 +1080,10 @@ Next steps: + [X] Discuss caching of group tag expansion. It seems like we ought to cache the expansions as well, because sibling headings (especially at level 1) ought to get their group tags re-expanded individually, even when we've already expanded them for another heading. + [X] Remove unused =result= variable -** PROJECT [#A] Checking links for unsafe parameters -:PROPERTIES: -:ID: ba70e375-eddb-40df-8892-fb418c1f70d1 -:END: -:LOGBOOK: -- State "PROJECT" from "UNDERWAY" [2020-11-12 Thu 00:26] -- State "UNDERWAY" from [2020-11-11 Wed 23:09] -:END: +** PROJECT [#B] Document the sorting functions -*** TODO Tag org-super-agenda 1.2 and bump required version in org-ql +Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. -That /should/ force the version of org-super-agenda with the fix to be installed when org-ql is upgraded. - -*** DONE Add automated tests -:LOGBOOK: -- State "UNDERWAY" from "TODO" [2020-11-12 Thu 00:24] -- State "TODO" from "MAYBE" [2020-11-11 Wed 23:16] -- State "MAYBE" from [2020-11-11 Wed 23:15] -:END: - -Maybe impractical, but maybe we could at least test that potentially unsafe ones signal errors. - -[2020-11-12 Thu 00:24] Works better than I expected. All the tests seem to correctly pass, signaling the correct errors for the correct reasons--except for the tests specific to org-super-agenda. For that, I'm currently waiting for MELPA to build the version of org-super-agenda that has the fix applied, so I can install that into the test sandbox, and then those two tests should pass also. - -*** DONE Enumerate and test parameters and potentially unsafe types -CLOSED: [2020-11-11 Wed 23:26] -:LOGBOOK: -- State "DONE" from "UNDERWAY" [2020-11-11 Wed 23:26] -- State "UNDERWAY" from [2020-11-11 Wed 23:15] -:END: - -#+CAPTION: Template for making testable links -#+BEGIN_SRC org -[[org-ql-search:todo:?]] -#+END_SRC - -#+CAPTION: Expression to insert encoded values into template (after the =?=) -#+BEGIN_SRC elisp - (insert (url-hexify-string (concat "buffers-files=" (prin1-to-string '((lambda () (message "AHA"))))))) -#+END_SRC - -+ [X] Buffers-Files: Expanded by =org-ql-view--expand-buffers-files=: - - [X] Quoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Quoted lambda in list (safe): [[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]] - - [X] Unquoted lambda in list: (safe) [[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]] -+ [X] Groups - - [X] Quoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Quoted expression (safe): [[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]] - - [X] Unquoted expression (safe): [[org-ql-search:todo:?super-groups%3D%22AHA%22]] - - [X] ~:pred~ selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] - - [X] =:auto-map= selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] -+ [X] Title - - [X] Quoted lambda (produces the same encoded value as unquoted lambda): (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Expression: (safe) [[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]] -+ [X] Sort - - [X] Bare, quoted lambda: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Bare, unquoted lambda: (UNSAFE, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Quoted lambda in list: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]] - - [X] Unquoted lambda in a list: (UNSAFE, but caught now): [[org-ql-search:todo:?sort=((lambda%20nil%20(message%20"AHA")))]] - -For the query expression: - -1. String queries are parsed by the PEG parsing function (which I will probably rename soon), which should only allow known Org QL predicates, not arbitrary functions. For example: - - #+BEGIN_SRC elisp - (org-ql--plain-query "message:AHA") ;;=> (regexp "message:AHA") - (org-ql--plain-query '(message "AHA")) ;;=> (wrong-type-argument stringp (message "AHA")) - (org-ql--plain-query "(message \"AHA\"") ;;=> (and (regexp "(message") (regexp "AHA")) - #+END_SRC - -2. Sexp queries already prompt for confirmation, unless the user has set =org-ql-view-ask-unsafe-links= to nil. - -[2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. ** PROJECT [#B] Recursive queries @@ -1286,7 +1357,7 @@ Appears to be another implementation of magit-section-like expandable sections. ** PROJECT Dynamic blocks -*** TODO [#B] Save view to dynamic block +*** PROJECT [#B] Save view to dynamic block :PROPERTIES: :milestone: 0.6 :END: @@ -1374,6 +1445,32 @@ For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this [2020-11-10 Tue 00:03] I think it's ready to merge now. +*** DONE [#A] Org block to insert results of queries with links to entries +:PROPERTIES: +:ID: 422754bb-3a7c-4dbf-b303-4056d3cafb7e +:END: + +[2020-01-16 Thu 06:20] This idea just came to me when I was thinking about using the search-based paradigm vs. outline-based. This would allow both, e.g. some kind of =#+BEGIN_QUERY= block that would update when =C-c C-c= is pressed on it. + +[2020-11-13 Fri 22:57] I keep rediscovering ideas that I've had previously. This is now done as the dynamic block feature. I guess I should actually use these tools I've made. + +** PROJECT [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] :compatibility: + +[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. + +** PROJECT [#C] Normalize queries + +[2019-07-16 Tue 11:49] This serves two purposes: + +1. Equivalent queries will return the same results from the cache. +2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file. + +So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. + +** PROJECT [#C] Update view screenshots + +e.g. doesn't currently show the =View= header. + ** PROJECT [#C] Test caching See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. @@ -1940,7 +2037,7 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled :END: :CONTENTS: -- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][{2019-08-29 Thu 06:24} Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] +- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][[2019-08-29 Thu 06:24] Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] - [[#caching-of-inherited-tags][Caching of inherited tags]] - [[#intersecting-query-results][Intersecting query results]] - [[#more-profiling][More profiling]] From 89ff02a1501b53b4e20cdc66a8fcaa37e7d15734 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 05:40:24 -0600 Subject: [PATCH 207/560] Fix: (org-ql--query-sexp-to-string) Ancestors, etc. queries --- org-ql.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index dc6ee24..f75ce4c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1778,7 +1778,11 @@ Multiple predicates are combined with BOOLEAN." If QUERY can't be converted to a string, return nil." ;; This started out pretty simple...but at least it's not just one long function, right? (cl-labels ((complex-p (query) - (or (contains-p 'or query))) + (or (contains-p 'or query) + (contains-p 'ancestors query) + (contains-p 'children query) + (contains-p 'descendants query) + (contains-p 'parent query))) (contains-p (symbol list) (cl-loop for element in list thereis (or (eq symbol element) From 0365b785cc075db0012bc919ef101f0b43ba9446 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 05:41:37 -0600 Subject: [PATCH 208/560] Fix: (org-ql--defpred) Add to predicates variable when compiling This seems to fix an occasional weird bug encountered when byte-compiling and loading this file. I can't explain why it only happens sometimes, but this seems to fix it, and it stands to reason why it does, so it seems like the right thing to do. --- org-ql.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index f75ce4c..3825ec2 100644 --- a/org-ql.el +++ b/org-ql.el @@ -159,7 +159,11 @@ match." (fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) (pred-name (intern (symbol-name name)))) `(progn - (push (list :name ',pred-name :aliases ',aliases :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates) + (cl-eval-when (compile load eval) + ;; When compiling, the predicate must be added to `org-ql-predicates' before `org-ql--def-plain-query-fn' + ;; is called to define `org-ql--plain-query'. Otherwise, `org-ql--plain-query' seems to work properly + ;; when interpreted but not always when the file is byte-compiled. + (push (list :name ',pred-name :aliases ',aliases :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates)) (cl-defun ,fn-name ,args ,docstring ,@body)))) ;; TODO: Mark as obsolete/deprecated. From 4a8deb541e9eb70afd54cbe1f4dbe29f375cdf4a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 05:43:12 -0600 Subject: [PATCH 209/560] Comment: Add FIXME --- org-ql-view.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-view.el b/org-ql-view.el index 843211e..f915591 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -683,6 +683,7 @@ When opened, the link searches the buffer it's opened from." "?" (url-build-query-string (delete nil params)))) (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil filename)))) + ;; FIXME: "Warning: ‘org-store-link-props’ is an obsolete function (as of Org 9.3); use ‘org-link-store-props’ instead" (org-store-link-props :type "org-ql-search" :link url From 1b12d4e9b0c5d4a5839434e80875f96f51d547ad Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 05:43:50 -0600 Subject: [PATCH 210/560] Fix: (org-ql-view--link-store) Don't re-format formatted queries org-ql-view--format-query already returns a string. --- org-ql-view.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index f915591..cba3ad9 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -669,7 +669,7 @@ When opened, the link searches the buffer it's opened from." (cl-every #'string-or-file-buffer-p org-ql-view-buffers-files))) (user-error "Views that search non-file-backed buffers can't be linked to")) (let* ((query-string (--if-let (org-ql--query-sexp-to-string org-ql-view-query) - it (prin1-to-string (org-ql-view--format-query org-ql-view-query)))) + it (org-ql-view--format-query org-ql-view-query))) (buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) (params (list (when buffers-files (list "buffers-files" buffers-files)) From 0a2b75146469074e36673957444935b9c68d27f8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:35:52 -0600 Subject: [PATCH 211/560] Fix: (org-ql-view-bookmark-make-record) List of filenames Fixes #148. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index cba3ad9..e4ac4c5 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -544,10 +544,12 @@ dates in the past, and negative for dates in the future." (defun org-ql-view-bookmark-make-record () "Return a bookmark record for the current Org QL View buffer." (cl-labels ((file-nameize - (b-f) (or (buffer-file-name b-f) - (when (buffer-base-buffer b-f) - (buffer-file-name (buffer-base-buffer b-f))) - (user-error "Only file-backed buffers can be bookmarked by Org QL View: %s" b-f)))) + (b-f) (cl-typecase b-f + (string b-f) + (buffer (or (buffer-file-name b-f) + (when (buffer-base-buffer b-f) + (buffer-file-name (buffer-base-buffer b-f))))) + (t (user-error "Only file-backed buffers can be bookmarked by Org QL View: %s" b-f))))) (pcase-let* ((plist (org-ql-view--plist (current-buffer))) ((map :buffers-files) plist)) ;; Replace buffers with their filenames, and signal error if any are not file-backed. From 5b401cd8b79086f6cdcca0bd22ef4267efa80851 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:36:28 -0600 Subject: [PATCH 212/560] Tidy: (org-ql-view-bookmark-make-record) --- org-ql-view.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index e4ac4c5..f5f7fb7 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -557,8 +557,7 @@ dates in the past, and negative for dates in the future." (cl-etypecase buffers-files (string buffers-files) (buffer (file-nameize buffers-files)) - (list (cl-loop for b-f in buffers-files - collect (file-nameize b-f)))))) + (list (mapcar #'file-nameize buffers-files))))) (list (concat "Org QL View: " org-ql-view-title) (cons 'org-ql-view-plist plist) (cons 'handler #'org-ql-view-bookmark-handler) From 60d0c2a45589bfeaccc0096dbb80ee13b32c5f24 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:53:30 -0600 Subject: [PATCH 213/560] Notes: Update --- notes.org | 139 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 60 deletions(-) diff --git a/notes.org b/notes.org index f0f0c59..48f914a 100644 --- a/notes.org +++ b/notes.org @@ -17,66 +17,63 @@ * [#A] Overview -** Bugs +** Bugs ([[org-ql-search:todo%253A%2520tags%253Abug?super-groups=%2528%2528%253Aauto-property%2520%2522Milestone%2522%2529%2529&sort=%2528todo%2529&title=%2522Bugs%2522][view]]) -+ [[org-ql-search:todo%3A%20tags%3Abug?super-groups=%28%28%3Aauto-property%20%22Milestone%22%29%29&sort=%28priority%29&title=%22Bugs%22][org-ql-search: Bugs]] - -#+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" -| P | M | Keyword | Heading | -|---+---+---------+---------------------------------------------------------------------| -| A | | NEXT | [[Fix query-sexp-to-string function's handling of, e.g. =descendants=][Fix query-sexp-to-string function's handling of, e.g. =descendants=]] | +#+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority todo date) :ts-format "%Y-%m-%d %H:%M" +| P | M | Keyword | Heading | +|---+-----+---------+------------------------------------------------| +| A | 0.5 | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | +| A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| A | 0.5 | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | #+END: -** Underway +** Underway ([[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][view]]) -+ [[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][org-ql-search: Underway]] - -#+BEGIN: org-ql :query (todo "UNDERWAY") :columns ((priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" -| P | Keyword | Heading | -|---+----------+--------------------------------------------------------------------| -| B | UNDERWAY | [["Node" caching]["Node" caching]] | -| | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | +#+BEGIN: org-ql :query (todo "UNDERWAY") :columns (((property "milestone") "M") (priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +| M | P | Keyword | Heading | +|---+---+----------+--------------------------------------------------------------------| +| | B | UNDERWAY | [["Node" caching]["Node" caching]] | +| | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | #+END: -** To-do +** To-do ([[org-ql-search:todo:?super-groups=((:todo%20"NEXT")%20(:todo%20"PROJECT")%20(:auto-priority))&sort=(todo)][view]]) -+ [[org-ql-search:todo%3A?super-groups=%28%28%3Atodo%20%22NEXT%22%29%20%28%3Atodo%20%22PROJECT%22%29%20%28%3Aauto-priority%29%29&sort=%28todo%29][org-ql-search: Tasks]] - -#+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") todo heading) :sort (priority date) :take 7 -| P | Todo | Heading | -|---+---------+----------------------------------------------------------------------------| -| A | NEXT | [[Fix query-sexp-to-string function's handling of, e.g. =descendants=][Fix query-sexp-to-string function's handling of, e.g. =descendants=]] | -| A | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | -| A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | PROJECT | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | -| A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| A | PROJECT | [[Org link types [2/3\]][Org link types [2/3]​]] | +#+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 +| P | M | Todo | Heading | +|---+-----+---------+--------------------------------------------------------------| +| A | | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | +| A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| A | 0.5 | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | +| A | 0.5 | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | +| A | | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| A | | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| A | 0.5 | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | #+END: -** [[org-ql-search:%28and%20%28todo%20%22PROJECT%22%29%20%28not%20%28descendants%20%28todo%20%22NEXT%22%29%29%29%29?super-groups=%28%28%3Aauto-parent%29%29&sort=%28priority%29&title=%22Stuck%20Projects%22][org-ql-search: Stuck Projects]] +** Stuck projects ([[org-ql-search:(and%20(todo%20"PROJECT")%20(not%20(descendants%20(todo%20"NEXT"))))?super-groups=((:auto-parent))&sort=(priority)&title="Stuck%20Projects"][view]]) -#+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns ((priority "P") heading) :sort (priority date) :take 7 -| P | Heading | -|---+----------------------------------------------------------------------------| -| A | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | -| A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| A | [[Org link types [2/3\]][Org link types [2/3]​]] | -| B | [[Outline path predicate][Outline path predicate]] | -| B | [[Group tag support][Group tag support]] | +#+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns (((property "milestone") "M") (priority "P") heading) :sort (priority date) :take 7 +| M | P | Heading | +|-----+---+-------------------------------------------------------| +| 0.5 | A | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| | A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| | A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| | A | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | +| | B | [[Move this notes file into an orphan =meta/notes= branch][Move this notes file into an orphan =meta/notes= branch]] | +| | B | [[Outline path predicate][Outline path predicate]] | +| | B | [[Group tag support][Group tag support]] | #+END: -** Milestones - -[[org-ql-search:todo%3A?super-groups=%28%28%3Aauto-property%20%22milestone%22%29%29&sort=%28todo%29&title=%22Milestones%22][org-ql-search: Milestones]] +** Milestones ([[org-ql-search:todo:?super-groups=((:auto-property%20"milestone"))&sort=(todo)&title="Milestones"][view]]) #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|-----+---+---------+----------------------------------------------------------------------------| -| 0.5 | A | PROJECT | [[Fix =org-ql-view--link-open= on newer Org versions][Fix =org-ql-view--link-open= on newer Org versions]] | -| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | +| M | P | Todo | Heading | +|-----+---+---------+--------------------------------------------------------------| +| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| 0.5 | A | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | +| 0.5 | A | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | +| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | #+END: * [#A] Tasks @@ -93,18 +90,17 @@ - [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] -- [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#node-caching]["Node" caching]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] - [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] -- [[#fix-org-ql-view--link-open-on-newer-org-versions][Fix org-ql-view--link-open on newer Org versions]] +- [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] - [[#outline-path-predicate][Outline path predicate]] -- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them [3/4]​]] +- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] - [[#document-the-sorting-functions][Document the sorting functions]] - [[#recursive-queries][Recursive queries]] @@ -115,6 +111,7 @@ - [[#normalize-queries][Normalize queries]] - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] +- [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] - [[#byte-compile-lambdas][Byte-compile lambdas]] @@ -172,10 +169,6 @@ e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. -** TODO [#B] Move this notes file into an orphan =meta/notes= branch - -[2020-11-12 Thu 03:17] Will probably have to merge or delete some WIP branches first, otherwise they'll probably get conflicts. - ** TODO [#C] ~org-agenda-skip-function~ As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: @@ -221,11 +214,6 @@ I should benchmark it to see how much difference it makes, because all those ~fs ** TODO [#C] Update commentary -** NEXT [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: -:PROPERTIES: -:milestone: 0.5 -:END: - ** NEXT [#A] Make dynamic blocks warn about sexp queries [2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. @@ -371,7 +359,7 @@ Eventually, the function org-export-custom-protocol-maybe is now called with a f Unfortunately it does not say what the new, required second argument is. -** PROJECT [#A] Fix =org-ql-view--link-open= on newer Org versions :compatibility:bug: +** PROJECT [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: :PROPERTIES: :milestone: 0.5 :END: @@ -384,6 +372,26 @@ I do recall something about links changing in Org 9.3 (or thereabouts), so that I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. +[2020-11-14 Sat 20:41] I should probably do something like this in =org-ql-view--link-open=: + +#+BEGIN_SRC elisp + (when (version<= "9.3" (org-version)) + ;; Org 9.3+ makes a backward-incompatible change to link escaping. + ;; I don't think it would be a good idea to try to guess whether + ;; the string received by this function was made with or without + ;; that change, so we'll just test the current version of Org. + ;; Any links created with older Org versions and then opened with + ;; newer ones will have to be recreated. + (setf path (url-unhex-string path))) +#+END_SRC + +But, first, I should write tests for saving and opening links, so it can actually be tested on different versions automatically. + +*** NEXT [#A] Write tests for storing/opening links +:PROPERTIES: +:milestone: 0.5 +:END: + *** DONE [#A] Check Org release notes for link changes [2020-11-13 Fri 22:44] From [[https://www.orgmode.org/Changes_old.html][the changelog]]: @@ -633,6 +641,10 @@ For the query expression: [2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. +** PROJECT [#B] Move this notes file into an orphan =meta/notes= branch + +[2020-11-12 Thu 03:17] Will probably have to merge or delete some WIP branches first, otherwise they'll probably get conflicts. + ** PROJECT [#B] Outline path predicate [2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: @@ -1475,6 +1487,13 @@ e.g. doesn't currently show the =View= header. See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. +** DONE [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: +:PROPERTIES: +:milestone: 0.5 +:END: + +[2020-11-14 Sat 20:45] Fixed in =89ff02a1501b53b4e20cdc66a8fcaa37e7d15734=. + ** DONE [#A] Helm command In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. @@ -2037,7 +2056,7 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled :END: :CONTENTS: -- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][[2019-08-29 Thu 06:24] Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] +- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][{2019-08-29 Thu 06:24} Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] - [[#caching-of-inherited-tags][Caching of inherited tags]] - [[#intersecting-query-results][Intersecting query results]] - [[#more-profiling][More profiling]] From 511edbfff85618be847dc992a17b6ff8b4405cfb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:58:19 -0600 Subject: [PATCH 214/560] Notes: Make ToC after sorting --- notes.org | 2 +- org-ql-view.el | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/notes.org b/notes.org index 48f914a..223a652 100644 --- a/notes.org +++ b/notes.org @@ -4184,6 +4184,6 @@ I don't need this right now, but it might come in handy here or elsewhere. ** File-local variables # Local Variables: -# before-save-hook: (org-make-toc (lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o)))))) +# before-save-hook: ((lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o))))) org-make-toc) # End: diff --git a/org-ql-view.el b/org-ql-view.el index f5f7fb7..0101a69 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -662,9 +662,10 @@ When opened, the link searches the buffer it's opened from." ("containing file" nil) (buffers-files (prin1-to-string buffers-files)))) (string-or-file-buffer-p - (thing) (or (stringp thing) - (and (bufferp thing) - (buffer-file-name thing))))) + (thing) (cl-typecase thing + (string thing) + (buffer (or (buffer-file-name thing) + (buffer-file-name (buffer-base-buffer thing))))))) (unless (or (string-or-file-buffer-p org-ql-view-buffers-files) (and (listp org-ql-view-buffers-files) (cl-every #'string-or-file-buffer-p org-ql-view-buffers-files))) From 5c8260b2721b29d78892c35691c9218d55d981c4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:58:32 -0600 Subject: [PATCH 215/560] Notes: Add checklist --- notes.org | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/notes.org b/notes.org index 223a652..b02ccae 100644 --- a/notes.org +++ b/notes.org @@ -1855,6 +1855,18 @@ If I made the =date= selector a macro, I could avoid the need to quote the compa Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc. +* Checklists + +** Commit + +*** Fix + ++ [ ] Check repo for closing issue ++ [ ] Check this file for closing task ++ [ ] Lint ++ [ ] Test ++ [ ] Commit and push + * Examples / testing :PROPERTIES: :TOC: :include descendants :depth 1 From dabb812a3c221d28bc6244032404aea8d3eeeb1d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 20:58:45 -0600 Subject: [PATCH 216/560] Notes: Update --- notes.org | 224 +++++++++++++++++++++++++++--------------------------- 1 file changed, 113 insertions(+), 111 deletions(-) diff --git a/notes.org b/notes.org index b02ccae..ebfa4a9 100644 --- a/notes.org +++ b/notes.org @@ -8,6 +8,7 @@ :CONTENTS: - [[#overview][Overview]] - [[#tasks][Tasks]] +- [[#checklists][Checklists]] - [[#examples--testing][Examples / testing]] - [[#in-the-wild][In the wild]] - [[#profiling][Profiling]] @@ -87,18 +88,17 @@ - [[#add-more-sorters][Add more sorters?]] - [[#default-sort][Default sort]] - [[#partial-match-for-property-queries][Partial match for property queries]] -- [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] -- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] -- [[#node-caching]["Node" caching]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] +- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] - [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] +- [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] - [[#outline-path-predicate][Outline path predicate]] - [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] - [[#group-tag-support][Group tag support]] @@ -111,6 +111,7 @@ - [[#normalize-queries][Normalize queries]] - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] +- [[#node-caching]["Node" caching]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] @@ -214,114 +215,6 @@ I should benchmark it to see how much difference it makes, because all those ~fs ** TODO [#C] Update commentary -** NEXT [#A] Make dynamic blocks warn about sexp queries - -[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. - -** UNDERWAY [#B] "Node" caching - -[2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. - -It would probably be an all-encompassing system, because predicates would need to refer to the cached node when available. So maybe the struct should be like =ts-defstruct=, with lazy, caching accessors, which would move some of the predicates' code into the accessors. - -Maybe a good improvement to make later, after the project is more developed. - -[2019-10-07 Mon 13:08] This has basically been implemented in =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but as functions and values rather than with structs. It remains to be seen how this works with =ancestor= queries, but I suspect it will help a lot. - -*** Struct PoC code - -This works okay (except the priority accessor needs to be fixed, because Org priorities are awkward to get). I'm guessing all the extra function calls would make it undesirable in cases of returning many results, but it's a flexible concept that makes sorting easy. - -#+BEGIN_SRC elisp - (ts-defstruct org-ql-node - file position marker - (level - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-outline-level))) - (heading - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - ;; TODO: Org 9.2+ adds 2 more args to `org-get-heading'. - (org-get-heading t t))) - (priority - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-get-priority ))) - (tags - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (->> (org-ql--tags-at (point)) - -flatten - (delq 'org-ql-nil)))) - (todo - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-get-todo-state))) - (outline-path - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-split-string (org-format-outline-path (org-get-outline-path) - nil nil "") - "")))) - - (defcustom helm-org-ql-sort - '(org-ql-node-priority org-ql-node-todo) - "FIXME" - ) - - (cl-defun helm-org-ql (buffers-files &optional no-and) - "Display results in BUFFERS-FILES for an `org-ql' query using Helm. - Interactively, search the current buffer. - - NOTE: Atoms in the query are turned into strings where - appropriate, which makes it unnecessary to type quotation marks - around words that are intended to be searched for as indepenent - strings. - - Also, unless NO-AND is non-nil (interactively, with prefix), all - query tokens are wrapped in an implied (and) form. This is - because a query must be a sexp, so when typing multiple clauses, - either (and) or (or) would be required around them, and (and) is - typically more useful, because it narrows down results. - - For example, this raw input: - - Emacs git - - Is transformed into this query: - - (and \"Emacs\" \"git\") - - However, quoted strings remain quoted, so this input: - - \"something else\" (tags \"funny\") - - Is transformed into this query: - - (and \"something else\" (tags \"funny\"))" - (interactive (list (current-buffer) current-prefix-arg)) - (let ((helm-input-idle-delay helm-org-ql-input-idle-delay)) - (helm :sources - (helm-build-sync-source "helm-org-ql-agenda-files" - :candidates (lambda () - (let* ((query (helm-org-ql--input-to-query helm-pattern no-and)) - (window-width (window-width (helm-window)))) - (when query - (let ((results (org-ql-select buffers-files - query - :action '(make-org-ql-node :marker (point-marker))))) - (when helm-org-ql-sort - (dolist (sorter (reverse helm-org-ql-sort)) - (setf results (sort results sorter)))) - (cl-loop for it in-ref results - do (setf it (concat (buffer-name (org-ql-node-file it)) ":" - (or (org-ql-node-todo it) "") - (or (org-ql-node-priority it) "") - (org-ql-node-heading it) "\\" - (org-ql-node-outline-path it)))) - results)))) - :match #'identity - :fuzzy-match nil - :multimatch nil - :volatile t - :action #'helm-org-goto-marker)))) -#+END_SRC - ** MAYBE [#C] Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. @@ -339,6 +232,10 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. +** NEXT [#A] Make dynamic blocks warn about sexp queries + +[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. + ** PROJECT [#A] Compatibility with Org 9.4 custom link changes :bug: :PROPERTIES: :milestone: 0.5 @@ -362,6 +259,7 @@ Unfortunately it does not say what the new, required second argument is. ** PROJECT [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: :PROPERTIES: :milestone: 0.5 +:url: https://github.com/alphapapa/org-ql/issues/147 :END: The version of Org in my personal that passes a URL-decoded string (i.e. as if run through =url-unhex-string=) as the argument to =org-ql-view--link-open=. But Org 9.3 in Emacs 27.1 passes a non-URL-decoded string, so =org-ql-view--link-open= needs to pass it through =url-unhex-string= itself. @@ -1487,6 +1385,110 @@ e.g. doesn't currently show the =View= header. See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. +** UNDERWAY [#B] "Node" caching + +[2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. + +It would probably be an all-encompassing system, because predicates would need to refer to the cached node when available. So maybe the struct should be like =ts-defstruct=, with lazy, caching accessors, which would move some of the predicates' code into the accessors. + +Maybe a good improvement to make later, after the project is more developed. + +[2019-10-07 Mon 13:08] This has basically been implemented in =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but as functions and values rather than with structs. It remains to be seen how this works with =ancestor= queries, but I suspect it will help a lot. + +*** Struct PoC code + +This works okay (except the priority accessor needs to be fixed, because Org priorities are awkward to get). I'm guessing all the extra function calls would make it undesirable in cases of returning many results, but it's a flexible concept that makes sorting easy. + +#+BEGIN_SRC elisp + (ts-defstruct org-ql-node + file position marker + (level + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + (org-outline-level))) + (heading + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + ;; TODO: Org 9.2+ adds 2 more args to `org-get-heading'. + (org-get-heading t t))) + (priority + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + (org-get-priority ))) + (tags + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + (->> (org-ql--tags-at (point)) + -flatten + (delq 'org-ql-nil)))) + (todo + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + (org-get-todo-state))) + (outline-path + nil :accessor-init (org-with-point-at (org-ql-node-marker struct) + (org-split-string (org-format-outline-path (org-get-outline-path) + nil nil "") + "")))) + + (defcustom helm-org-ql-sort + '(org-ql-node-priority org-ql-node-todo) + "FIXME" + ) + + (cl-defun helm-org-ql (buffers-files &optional no-and) + "Display results in BUFFERS-FILES for an `org-ql' query using Helm. + Interactively, search the current buffer. + + NOTE: Atoms in the query are turned into strings where + appropriate, which makes it unnecessary to type quotation marks + around words that are intended to be searched for as indepenent + strings. + + Also, unless NO-AND is non-nil (interactively, with prefix), all + query tokens are wrapped in an implied (and) form. This is + because a query must be a sexp, so when typing multiple clauses, + either (and) or (or) would be required around them, and (and) is + typically more useful, because it narrows down results. + + For example, this raw input: + + Emacs git + + Is transformed into this query: + + (and \"Emacs\" \"git\") + + However, quoted strings remain quoted, so this input: + + \"something else\" (tags \"funny\") + + Is transformed into this query: + + (and \"something else\" (tags \"funny\"))" + (interactive (list (current-buffer) current-prefix-arg)) + (let ((helm-input-idle-delay helm-org-ql-input-idle-delay)) + (helm :sources + (helm-build-sync-source "helm-org-ql-agenda-files" + :candidates (lambda () + (let* ((query (helm-org-ql--input-to-query helm-pattern no-and)) + (window-width (window-width (helm-window)))) + (when query + (let ((results (org-ql-select buffers-files + query + :action '(make-org-ql-node :marker (point-marker))))) + (when helm-org-ql-sort + (dolist (sorter (reverse helm-org-ql-sort)) + (setf results (sort results sorter)))) + (cl-loop for it in-ref results + do (setf it (concat (buffer-name (org-ql-node-file it)) ":" + (or (org-ql-node-todo it) "") + (or (org-ql-node-priority it) "") + (org-ql-node-heading it) "\\" + (org-ql-node-outline-path it)))) + results)))) + :match #'identity + :fuzzy-match nil + :multimatch nil + :volatile t + :action #'helm-org-goto-marker)))) +#+END_SRC + ** DONE [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: :PROPERTIES: :milestone: 0.5 From 8a1fd1459081f5639a8c2d58289bb1fe4e095ea9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 14 Nov 2020 22:29:53 -0600 Subject: [PATCH 217/560] Fix: (org-ql-view--link-store) Indirect buffers Probably the best thing to do, even if it's not "correct" in a sense. --- org-ql-view.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 0101a69..062c9e9 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -662,10 +662,15 @@ When opened, the link searches the buffer it's opened from." ("containing file" nil) (buffers-files (prin1-to-string buffers-files)))) (string-or-file-buffer-p - (thing) (cl-typecase thing + (thing) (cl-etypecase thing (string thing) (buffer (or (buffer-file-name thing) - (buffer-file-name (buffer-base-buffer thing))))))) + ;; TODO: Should indirect buffers be allowed? Maybe not, since their narrowing isn't preserved. + ;; On the other hand, it's possible to accidentally make a search view for an indirect buffer + ;; that's since been widened, and forcing the user to manually change that would be awkward, + ;; and trying to communicate the problem would be difficult, so maybe it's okay to allow it. + (when (buffer-base-buffer thing) + (buffer-file-name (buffer-base-buffer thing)))))))) (unless (or (string-or-file-buffer-p org-ql-view-buffers-files) (and (listp org-ql-view-buffers-files) (cl-every #'string-or-file-buffer-p org-ql-view-buffers-files))) From b04d0263a4e0d072a8c7fbb6d50af24f5193b236 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 15 Nov 2020 21:07:51 -0600 Subject: [PATCH 218/560] Notes: Update --- notes.org | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/notes.org b/notes.org index ebfa4a9..c15d42a 100644 --- a/notes.org +++ b/notes.org @@ -82,6 +82,7 @@ :TOC: :include descendants :depth 1 :END: :CONTENTS: +- [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] @@ -122,6 +123,11 @@ - [[#use-macros-for-date][Use macros for date]] :END: +** TODO [#A] Add Emacs 27.1 to =test.yml= +:PROPERTIES: +:milestone: 0.5 +:END: + ** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. From 9d86ee9e1098fef5b4a17e98321f522f6d8fc20b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 02:02:22 -0600 Subject: [PATCH 219/560] Change/Fix: Bookmark, link storing/loading/safety This makes several changes and fixes and adds test cases for all the combinations I'm aware of. See #147. Thanks to @tpeacock19 for patiently reporting these issues. Squashed commit of the following: commit d1b396c5654ae3fa8ad03d0d4b2cbde20000fa1a Author: Adam Porter Date: Mon Nov 16 02:01:23 2020 -0600 WIP: Fixes commit 23215a723c4bf6e249c330863e01029166db56c3 Author: Adam Porter Date: Mon Nov 16 01:34:34 2020 -0600 WIP: Fixes commit 97b13d09d4d52bb168bfc19fb6f8daf2964f4b6c Author: Adam Porter Date: Mon Nov 16 00:46:49 2020 -0600 WIP: Test links too Everything passes now. commit 1866a71dbbb6416f7e365c90cadd269765d52b70 Author: Adam Porter Date: Sun Nov 15 22:22:22 2020 -0600 WIP: Test loading/saving bookmarks --- org-ql-view.el | 62 +++++---- org-ql.el | 2 + tests/test-org-ql.el | 321 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 310 insertions(+), 75 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 062c9e9..8e8d40b 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -620,7 +620,7 @@ protocol. See, e.g. `org-ql-view--link-store'." (read-value (read stored-string))) ;; Ensure the value is either a symbol or list of symbols (which excludes lambdas). (unless (or (symbolp read-value) (cl-every #'symbolp read-value)) - (error "Potentially unsafe value found in link's SORT parameter (%s). Link not opened" + (error "CAUTION: Link not opened because unsafe sort parameter detected: %s" read-value)) read-value)) (org-super-agenda-allow-unsafe-groups nil) ; Disallow unsafe group selectors. @@ -631,6 +631,10 @@ protocol. See, e.g. `org-ql-view--link-store'." (buffers-files (--if-let (alist-get "buffers-files" params nil nil #'string=) (org-ql-view--expand-buffers-files (read it)) (current-buffer)))) + (unless (or (bufferp buffers-files) + (stringp buffers-files) + (cl-every #'stringp buffers-files)) + (error "CAUTION: Link not opened because unsafe buffers-files parameter detected: %s" buffers-files)) (when (and org-ql-view-ask-unsafe-links (or (string-match (rx bol (0+ space) "(") query) (listp query))) @@ -655,31 +659,31 @@ When opened, the link searches the buffer it's opened from." (require 'url-util) (when org-ql-view-query ;; Only Org QL View buffers should have `org-ql-view-query' set. - (cl-flet ((prompt-for (buffers-files) - (pcase-exhaustive - (completing-read (format "Link to search file containing inserted link or %s? " buffers-files) - (list "containing file" buffers-files) nil t) - ("containing file" nil) - (buffers-files (prin1-to-string buffers-files)))) - (string-or-file-buffer-p - (thing) (cl-etypecase thing - (string thing) - (buffer (or (buffer-file-name thing) - ;; TODO: Should indirect buffers be allowed? Maybe not, since their narrowing isn't preserved. - ;; On the other hand, it's possible to accidentally make a search view for an indirect buffer - ;; that's since been widened, and forcing the user to manually change that would be awkward, - ;; and trying to communicate the problem would be difficult, so maybe it's okay to allow it. - (when (buffer-base-buffer thing) - (buffer-file-name (buffer-base-buffer thing)))))))) - (unless (or (string-or-file-buffer-p org-ql-view-buffers-files) - (and (listp org-ql-view-buffers-files) - (cl-every #'string-or-file-buffer-p org-ql-view-buffers-files))) + (cl-labels ((prompt-for (buffers-files) + (pcase-exhaustive + (completing-read (format "Make link that searches: ") + '("file link is in" "files currently searched") + nil t nil nil "file link is in") + ("file link is in" nil) + ("files currently searched" buffers-files))) + (strings-or-file-buffers-p + (thing) (cl-etypecase thing + (list (cl-every #'strings-or-file-buffers-p thing)) + (string thing) + (buffer (or (buffer-file-name thing) + ;; TODO: Should indirect buffers be allowed? Maybe not, since their narrowing isn't preserved. + ;; On the other hand, it's possible to accidentally make a search view for an indirect buffer + ;; that's since been widened, and forcing the user to manually change that would be awkward, + ;; and trying to communicate the problem would be difficult, so maybe it's okay to allow it. + (when (buffer-base-buffer thing) + (buffer-file-name (buffer-base-buffer thing)))))))) + (unless (strings-or-file-buffers-p org-ql-view-buffers-files) (user-error "Views that search non-file-backed buffers can't be linked to")) (let* ((query-string (--if-let (org-ql--query-sexp-to-string org-ql-view-query) it (org-ql-view--format-query org-ql-view-query))) (buffers-files (prompt-for (org-ql-view--contract-buffers-files org-ql-view-buffers-files))) (params (list (when buffers-files - (list "buffers-files" buffers-files)) + (list "buffers-files" (prin1-to-string buffers-files))) (when org-ql-view-super-groups (list "super-groups" (prin1-to-string org-ql-view-super-groups))) (when org-ql-view-sort @@ -1037,16 +1041,14 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." "org-agenda-files") ((pred (seq-set-equal-p (org-ql-search-directories-files))) "org-directory") - (_ (let ((print-length nil)) - (concat "'" (prin1-to-string buffers-files)))))) + (_ buffers-files))) ((pred (equal (current-buffer))) "buffer") ((or 'org-agenda-files '(function org-agenda-files)) "org-agenda-files") ((and (pred bufferp) (guard (buffer-file-name buffers-files))) (buffer-file-name buffers-files)) - (_ (let ((print-length nil)) - (prin1-to-string buffers-files)))))) + (_ buffers-files)))) (defun org-ql-view--complete-buffers-files () "Return value for `org-ql-view-buffers-files' using completion." @@ -1068,13 +1070,15 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." "Return BUFFERS-FILES expanded to a list of files or buffers. The counterpart to `org-ql-view--contract-buffers-files'." (pcase-exhaustive buffers-files - ((pred bufferp) buffers-files) - ((or "" "buffer") (current-buffer)) - ("org-agenda-files" (org-agenda-files)) ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) (buffer-list))) + ("org-agenda-files" (org-agenda-files)) ("org-directory" (org-ql-search-directories-files)) - (else (s-split (rx (1+ space)) else)))) + ((or "" "buffer") (current-buffer)) + ((pred bufferp) buffers-files) + ((pred listp) buffers-files) + ;; A single filename. + ((pred stringp) buffers-files))) (defun org-ql-view--complete-super-groups () "Return value for `org-ql-view-super-groups' using completion." diff --git a/org-ql.el b/org-ql.el index 3825ec2..3b97307 100644 --- a/org-ql.el +++ b/org-ql.el @@ -225,6 +225,8 @@ returns nil or non-nil." (list buffers-or-files) (otherwise (list buffers-or-files))) (--map (cl-etypecase it + ;; NOTE: This etypecase is essential to opening links safely, + ;; as it rejects, e.g. lambdas in the buffers-files argument. (buffer it) (string (or (find-buffer-visiting it) (when (file-readable-p it) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 95519e8..f9499b7 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2019 Adam Porter ;; Author: Adam Porter -;; Package-Requires: ((buttercup)) +;; Package-Requires: ((buttercup) (with-simulated-input)) ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ ;;;; Requirements (require 'buttercup) +(require 'with-simulated-input) (require 'org-ql) @@ -1166,6 +1167,11 @@ RESULTS should be a list of strings as returned by ;; different reason. Were it not for testing the specific error AND its arguments, that test ;; case would have apparently passed, but it would have hidden the mistake in the test. + ;; NOTE: Rather than calling `message' in the "evil" lambdas (which, if it succeeds + ;; in being evil, merely writes a string to the test output, which is EASILY missed), + ;; we call `error', which, in combination with testing for specific error types and + ;; arguments, correctly causes tests to fail if the unsafe condition is not caught. + ;; Also, while writing these tests, the version of org-super-agenda in the test sandbox does ;; not have the fix applied yet, and the test for that apparently, correctly does not pass yet. @@ -1187,72 +1193,295 @@ RESULTS should be a list of strings as returned by (backward-char 1) (call-interactively #'org-open-at-point)))) - (it "buffers-files parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (quoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]]") - (unquoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]]")) + (describe "buffers-files parameter" + :var ((quoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29%29]]")) + (it "Errors for a quoted lambda" (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: (lambda nil (error UNSAFE))"))) + (it "Errors for an unquoted lambda" (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(stringp (lambda nil (message "AHA")))) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: (lambda nil (error UNSAFE))"))) + (it "Errors for a quoted lambda in a list" (expect (open-link quoted-lambda-in-list-link) - :to-throw 'wrong-type-argument '(stringp ((quote (lambda nil (message "AHA")))))) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ((quote (lambda nil (error UNSAFE))))"))) + (it "Errors for an unquoted lambda in a list" (expect (open-link unquoted-lambda-in-list-link) - :to-throw 'wrong-type-argument '(stringp ((lambda nil (message "AHA"))))))) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ((lambda nil (error UNSAFE)))")))) - (it "super-groups parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]]") - (quoted-expression-link "[[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]]") - (unquoted-expression-link "[[org-ql-search:todo:?super-groups%3D%22AHA%22]]") - (pred-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]") - (auto-map-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]]")) + (describe "super-groups parameter" + :var ((quoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28error%20%22UNSAFE%22%29%29]]") + (quoted-expression-link "[[org-ql-search:todo:?super-groups%3D%28error%20%22UNSAFE%22%29]]") + (unquoted-expression-link "[[org-ql-search:todo:?super-groups%3D%22UNSAFE%22]]") + (pred-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28error%20%22UNSAFE%22%29%29%29%29]]") + (auto-map-selector-link "[[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28error%20%22UNSAFE%22%29%29%29%29]]")) + (it "Errors for a quoted lambda" (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(listp lambda)) + :to-throw 'wrong-type-argument '(listp lambda))) + (it "Errors for an unquoted lambda" (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(listp lambda)) + :to-throw 'wrong-type-argument '(listp lambda))) + (it "Errors for a quoted expression" (expect (open-link quoted-expression-link) - :to-throw 'wrong-type-argument '(listp message)) + :to-throw 'wrong-type-argument '(listp error))) + (it "Errors for an unquoted expression" (expect (open-link unquoted-expression-link) - :to-throw 'error '("cl-etypecase failed: AHA, (symbol list)")) + :to-throw 'error '("cl-etypecase failed: UNSAFE, (symbol list)"))) - ;; FIXME: These two tests will not pass (i.e. they will not - ;; signal an error) until the version of org-super-agenda in - ;; the test sandbox is upgraded, which I'll do when MELPA - ;; packages the latest version. On the bright side, I just - ;; confirmed that, without the fix to org-super-agenda, - ;; these are vulnerable, which means that the test catches - ;; this problem and detects the fix. + ;; NOTE: These two tests depend on `org-super-agenda' to signal these errors. It's probably better + ;; to catch these in `org-super-agenda' rather than in `org-ql', because if other potentially unsafe + ;; selectors were added to org-super-agenda, org-ql would have to play catch-up, adding more tests. + ;; Catching them in org-super-agenda means that it can add more checks itself in the future. + (it "Errors for a :pred group" (expect (open-link pred-selector-link) - :to-throw 'error '("Unsafe groups disallowed (:pred): (lambda (_) (message AHA))")) + :to-throw 'error '("Unsafe groups disallowed (:pred): (lambda (_) (error UNSAFE))"))) + (it "Errors for an :auto-map group" (expect (open-link auto-map-selector-link) - :to-throw 'error '("Unsafe groups disallowed (:auto-map): ((lambda (_) (message AHA)))")))) + :to-throw 'error '("Unsafe groups disallowed (:auto-map): ((lambda (_) (error UNSAFE)))")))) - (it "title parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (expression-link "[[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]]")) + (describe "title parameter" + :var ((quoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]") + (expression-link "[[org-ql-search:todo:?title%3D%28error%20%22UNSAFE%22%29]]")) + (it "Errors for a quoted lambda" (expect (open-link quoted-lambda-link) - :to-throw 'wrong-type-argument '(characterp lambda)) + :to-throw 'wrong-type-argument '(characterp lambda))) + (it "Errors for an unquoted lambda" (expect (open-link unquoted-lambda-link) - :to-throw 'wrong-type-argument '(characterp lambda)) + :to-throw 'wrong-type-argument '(characterp lambda))) + (it "Errors for an expression" (expect (open-link expression-link) - :to-throw 'wrong-type-argument '(characterp message)))) + :to-throw 'wrong-type-argument '(characterp error)))) - (it "sort parameter" - (let ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (unquoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]]") - (quoted-lambda-in-list-link "[[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]]") - (unquoted-lambda-in-list-link "[[org-ql-search:todo:?sort=((lambda%20nil%20(message%20\"AHA\")))]]")) + (describe "sort parameter" + :var ((quoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]") + (unquoted-lambda-link "[[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29]]") + (quoted-lambda-in-list-link "[[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28error%20%22UNSAFE%22%29%29%29%29]]") + (unquoted-lambda-in-list-link "[[org-ql-search:todo:?sort=((lambda%20nil%20(error%20\"UNSAFE\")))]]")) + (it "Errors for a quoted lambda" (expect (open-link quoted-lambda-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: (lambda (_ _) (error UNSAFE))"))) + (it "Errors for an unquoted lambda" (expect (open-link unquoted-lambda-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter ((lambda (_ _) (message AHA))). Link not opened")) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: (lambda (_ _) (error UNSAFE))"))) + (it "Errors for a quoted lambda in a list" (expect (open-link quoted-lambda-in-list-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((quote (lambda (_ _) (message AHA))))). Link not opened")) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ((quote (lambda (_ _) (error UNSAFE))))"))) + (it "Errors for an unquoted lambda in a list" (expect (open-link unquoted-lambda-in-list-link) - :to-throw 'error '("Potentially unsafe value found in link’s SORT parameter (((lambda nil (message AHA)))). Link not opened")))))))) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ((lambda nil (error UNSAFE)))"))))))) + + (describe "View saving/loading" + :var* ((temp-dir (make-temp-file "test-org-ql-" 'dir)) + (temp-filenames (cl-loop for file in '("test1.org" "test2.org") + collect (expand-file-name file temp-dir))) + (file-contents (with-temp-buffer + (insert "#+TITLE: Test data\n\n" + "* TODO Heading 1\n" + "Heading 1 text.\n\n" + "* Heading 2\n" + "Heading 2 text.\n") + (buffer-string)))) + + ;; This section will test saving and loading search views by a few different + ;; means. In each one, the values of these buffer-local variables will be + ;; stored before saving a view and compared after loading it: + + ;; - org-ql-view-buffers-files + ;; - org-ql-view-query + ;; - org-ql-view-sort + ;; - org-ql-view-super-groups + ;; - org-ql-view-title + + ;; `org-ql-view-buffers-files' needs to be tested with these kinds of values: + + ;; - A buffer + ;; - A string (filename) + ;; - List of buffers + ;; - List of strings (filenames) + ;; - Combination + + ;; `org-ql-view-query' needs to be tested with these kinds of values: + + ;; - String query + ;; - Sexp query + + ;; `org-ql-view-sort' needs to be tested with these kinds of values: + + ;; - Symbol + ;; - List of symbols + + ;; `org-ql-view-super-groups' can probably be tested with nearly + ;; any list value (because this set of tests is not intended to + ;; test link safety). + + ;; TODO: `org-ql-view-title' needs to be tested with a string value. + + (before-all + (dolist (filename temp-filenames) + (with-temp-file filename + (insert file-contents)))) + + (after-all + (delete-directory temp-dir 'recursive)) + + (describe "Bookmarks" + :var ((title "ORG-QL-TEST") + bookmark-alist + view-buffer) + + (before-each + (setf view-buffer (get-buffer-create "*TEST*")) + (dolist (filename temp-filenames) + ;; Kill any existing buffers visiting these files. + (when-let ((buffer (find-file-noselect filename 'nowarn))) + (kill-buffer buffer)))) + + (cl-flet ((var-after-bookmark-set-and-jump + (var buffers-files query &key sort super-groups) + (org-ql-search buffers-files query + :super-groups super-groups + :sort sort :title title :buffer view-buffer) + (set-buffer view-buffer) + (bookmark-set title) + (kill-buffer) + (bookmark-jump title) + (buffer-local-value var (get-buffer (concat "*Org QL View: " title "*"))))) + + (describe "Grouping" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (super-groups '((:auto-priority)))) + (it "is restored" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-super-groups temp-filenames query + :super-groups super-groups) + :to-equal super-groups))) + + (describe "Queries" + :var ((string-query "todo:TODO regexp:heading") + (sexp-query '(and (todo "TODO") (regexp "heading")))) + (it "Sexps match" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-query temp-filenames sexp-query) :to-equal sexp-query)) + (it "Strings match" + ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. + (expect (var-after-bookmark-set-and-jump 'org-ql-view-query temp-filenames string-query) + :to-equal sexp-query))) + + (describe "Sorting" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (sorter 'todo) + (multiple-sorters '(todo priority))) + (it "One sorter is restored" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-sort temp-filenames query :sort sorter) + :to-equal sorter)) + (it "Multiple sorters are restored" + ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. + (expect (var-after-bookmark-set-and-jump 'org-ql-view-sort temp-filenames query :sort multiple-sorters) + :to-equal multiple-sorters))) + + (describe "Buffers/Files" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (one-filename (car temp-filenames))) + (it "One filename matches" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files one-filename query) + :to-equal one-filename)) + (it "A list of filenames matches" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files temp-filenames query) + :to-equal temp-filenames)) + ;; NOTE: These actually bookmark the filenames backing the buffers. + (it "One buffer matches" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files + (find-file-noselect (car temp-filenames)) query) + :to-equal one-filename)) + (it "A list of buffers matches" + (expect (var-after-bookmark-set-and-jump 'org-ql-view-buffers-files + (mapcar #'find-file-noselect temp-filenames) query) + :to-equal temp-filenames))))) + + (describe "Links" + ;; Not sure if this binding works. + :var ((title "ORG-QL-TEST") + (view-buffer-name "*TEST VIEW BUFFER*") + link-buffer view-buffer) + + (before-each + (kill-buffer (get-buffer view-buffer-name)) + (setf link-buffer (get-buffer-create "*TEST LINK BUFFER*") + view-buffer (get-buffer-create view-buffer-name)) + (with-current-buffer link-buffer + (erase-buffer) + (insert "* TODO Test heading\n\n") + (org-mode))) + + (cl-flet ((var-after-link-save-open + (var buffers-files query &key sort super-groups (input "RET")) + (org-ql-search buffers-files query + :super-groups super-groups + :sort sort :title title :buffer view-buffer) + (with-current-buffer view-buffer + (with-simulated-input input + ;; Avoid writing "Stored: ..." to test output. + (let ((inhibit-message t)) + (org-store-link nil))) + (kill-buffer)) + ;; ;; Let's see if this trick works. + (org-open-link-from-string (caar org-stored-links) nil link-buffer) + (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) + (prog1 (buffer-local-value var (current-buffer)) + (kill-buffer))))) + + (describe "Queries" + :var ((string-query "todo:TODO regexp:heading") + (sexp-query '(and (todo "TODO") (regexp "heading")))) + (it "Sexps match" + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query) :to-equal sexp-query)) + (it "Strings match" + ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames string-query) + :to-equal sexp-query))) + + (describe "Grouping" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (super-groups '((:auto-priority)))) + (it "is restored" + (expect (var-after-link-save-open 'org-ql-view-super-groups temp-filenames query + :super-groups super-groups) + :to-equal super-groups))) + + (describe "Sorting" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (sorter 'todo) + (multiple-sorters '(todo priority))) + (it "One sorter is restored" + (expect (var-after-link-save-open 'org-ql-view-sort temp-filenames query :sort sorter) + :to-equal sorter)) + (it "Multiple sorters are restored" + ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. + (expect (var-after-link-save-open 'org-ql-view-sort temp-filenames query :sort multiple-sorters) + :to-equal multiple-sorters))) + + (describe "Buffers/Files" + :var ((query '(and (todo "TODO") (regexp "heading"))) + (one-buffer (find-file-noselect (car temp-filenames))) + (one-filename (car temp-filenames)) + (buffers (mapcar #'find-file-noselect temp-filenames))) + (it "Can search buffer containing the link" + (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query) + :to-equal link-buffer)) + (it "Can search a file by filename" + (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query + :input "M-n M-n RET") + :to-equal one-filename)) + (it "Can search multiple files by filename" + (expect (var-after-link-save-open 'org-ql-view-buffers-files temp-filenames query + :input "M-n M-n RET") + :to-equal temp-filenames))))) + + ;; MAYBE: Also test `org-ql-views', although I already know it works now. + ;; (describe "org-ql-views") + )) ;; Local Variables: ;; truncate-lines: t From e39fb1be5a16202f6f757f170781aebced955ae5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 02:11:38 -0600 Subject: [PATCH 220/560] Tests: Tidy --- tests/test-org-ql.el | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index f9499b7..ee9b772 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1464,9 +1464,7 @@ RESULTS should be a list of strings as returned by (describe "Buffers/Files" :var ((query '(and (todo "TODO") (regexp "heading"))) - (one-buffer (find-file-noselect (car temp-filenames))) - (one-filename (car temp-filenames)) - (buffers (mapcar #'find-file-noselect temp-filenames))) + (one-filename (car temp-filenames))) (it "Can search buffer containing the link" (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query) :to-equal link-buffer)) From 0d12cdb3f5a0bc2a80803ae762c26766c76ceafe Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 02:25:45 -0600 Subject: [PATCH 221/560] Fix: (org-ql-search-directories-files) Error unless org-directory Fixes #139. Thanks to Matt Huszagh (@matthuszagh) for reporting. Released as 0.4.7. --- README.org | 5 ++ org-ql-search.el | 9 ++-- org-ql.info | 130 ++++++++++++++++++++++++++--------------------- 3 files changed, 84 insertions(+), 60 deletions(-) diff --git a/README.org b/README.org index a7d79eb..23c4a9d 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.7 + +*Fixed* ++ Give a useful error if =org-ql-search-directories-files= is called without a directories argument and =org-directory= doesn't exist. (Fixes [[https://github.com/alphapapa/org-ql/issues/139][#139]]. Thanks to [[https://github.com/matthuszagh][Matt Huszagh]] for reporting.) + ** 0.4.6 *Fixed* diff --git a/org-ql-search.el b/org-ql-search.el index d97d59e..cf49281 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -270,9 +270,12 @@ automatically from the query." ;;;; Functions -(cl-defun org-ql-search-directories-files (&key (directories (list org-directory)) - (recurse org-ql-search-directories-files-recursive) - (regexp org-ql-search-directories-files-regexp)) +(cl-defun org-ql-search-directories-files + (&key (directories (if (file-exists-p org-directory) + (list org-directory) + (user-error "org-ql-search-directories-files: No DIRECTORIES given, and `org-directory' doesn't exist"))) + (recurse org-ql-search-directories-files-recursive) + (regexp org-ql-search-directories-files-regexp)) "Return list of matching files in DIRECTORIES, a list of directory paths. When RECURSE is non-nil, recurse into subdirectories. When REGEXP is non-nil, only return files that match REGEXP." diff --git a/org-ql.info b/org-ql.info index 213b610..6e8a77d 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros Changelog +* 0.4.7: 047. * 0.4.6: 046. * 0.4.5: 045. * 0.4.4: 044. @@ -709,6 +710,7 @@ releases. * Menu: +* 0.4.7: 047. * 0.4.6: 046. * 0.4.5: 045. * 0.4.4: 044. @@ -726,9 +728,22 @@ releases. * 0.1: 01.  -File: README.info, Node: 046, Next: 045, Up: Changelog +File: README.info, Node: 047, Next: 046, Up: Changelog -5.1 0.4.6 +5.1 0.4.7 +========= + +*Fixed* + • Give a useful error if org-ql-search-directories-files is called + without a directories argument and org-directory doesn’t exist. + (Fixes #139 (https://github.com/alphapapa/org-ql/issues/139). + Thanks to Matt Huszagh (https://github.com/matthuszagh) for + reporting.) + + +File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog + +5.2 0.4.6 ========= *Fixed* @@ -741,7 +756,7 @@ File: README.info, Node: 046, Next: 045, Up: Changelog  File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog -5.2 0.4.5 +5.3 0.4.5 ========= *Fixed* @@ -753,7 +768,7 @@ File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog  File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog -5.3 0.4.4 +5.4 0.4.4 ========= *Fixed* @@ -765,7 +780,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.4 0.4.3 +5.5 0.4.3 ========= *Fixed* @@ -775,7 +790,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.5 0.4.2 +5.6 0.4.2 ========= *Fixed* @@ -784,7 +799,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.6 0.4.1 +5.7 0.4.1 ========= *Fixed* @@ -794,7 +809,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.7 0.4 +5.8 0.4 ======= _Note:_ The next release, 0.5, may include changes which will require @@ -875,7 +890,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.8 0.3.2 +5.9 0.3.2 ========= *Fixed* @@ -888,8 +903,8 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.9 0.3.1 -========= +5.10 0.3.1 +========== *Fixed* • Compatibility with Org 9.2. Thanks to Brian Leung @@ -898,7 +913,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.10 0.3 +5.11 0.3 ======== *Added* @@ -963,7 +978,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.11 0.2.3 +5.12 0.2.3 ========== *Fixed* @@ -973,7 +988,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.12 0.2.2 +5.13 0.2.2 ========== *Fixed* @@ -984,7 +999,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.13 0.2.1 +5.14 0.2.1 ========== *Fixed* @@ -994,7 +1009,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.14 0.2 +5.15 0.2 ======== *Added* @@ -1077,7 +1092,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.15 0.1 +5.16 0.1 ======== First tagged release. @@ -1138,46 +1153,47 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1492 -Node: Screenshots1666 -Node: Installation1784 -Node: Quelpa2422 -Node: Usage2865 -Node: Commands3214 -Node: org-ql-search3687 -Node: helm-org-ql5335 -Node: org-ql-view5747 -Node: org-ql-view-sidebar5945 -Node: org-ql-view-recent-items6301 -Node: org-ql-sparse-tree6785 -Node: Queries7585 -Node: Non-sexp query syntax8493 -Node: General predicates10200 -Node: Ancestor/descendant predicates15007 -Node: Date/time predicates16135 -Node: Functions / Macros18790 -Node: Agenda-like views19023 -Node: Listing / acting-on results20428 -Node: Changelog25030 -Node: 04625649 -Node: 04526037 -Node: 04426396 -Node: 04326753 -Node: 04226948 -Node: 04127107 -Node: 0427346 -Node: 03231277 -Node: 03131654 -Node: 0331849 -Node: 02334824 -Node: 02235052 -Node: 02135320 -Node: 0235519 -Node: 0139554 -Node: Notes39655 -Node: Comparison with Org Agenda searches39817 -Node: org-sidebar40688 -Node: License40967 +Node: Contents1507 +Node: Screenshots1681 +Node: Installation1799 +Node: Quelpa2437 +Node: Usage2880 +Node: Commands3229 +Node: org-ql-search3702 +Node: helm-org-ql5350 +Node: org-ql-view5762 +Node: org-ql-view-sidebar5960 +Node: org-ql-view-recent-items6316 +Node: org-ql-sparse-tree6800 +Node: Queries7600 +Node: Non-sexp query syntax8508 +Node: General predicates10215 +Node: Ancestor/descendant predicates15022 +Node: Date/time predicates16150 +Node: Functions / Macros18805 +Node: Agenda-like views19038 +Node: Listing / acting-on results20443 +Node: Changelog25045 +Node: 04725679 +Node: 04626062 +Node: 04526462 +Node: 04426821 +Node: 04327178 +Node: 04227373 +Node: 04127532 +Node: 0427771 +Node: 03231702 +Node: 03132079 +Node: 0332276 +Node: 02335251 +Node: 02235479 +Node: 02135747 +Node: 0235946 +Node: 0139981 +Node: Notes40082 +Node: Comparison with Org Agenda searches40244 +Node: org-sidebar41115 +Node: License41394  End Tag Table From 77702850026722ebea730e2124288e826060180e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 02:37:49 -0600 Subject: [PATCH 222/560] Fix: (org-ql-view--contract-buffers-files) Non-existent org-directory Fixes #138. Fixes #139. Thanks to Matt Huszagh (@matthuszagh) for reporting. This *actually* fixes those issues. The 0.4.7 release is related to those issues, but those issues actually arose in code added to 0.5-pre. --- org-ql-view.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/org-ql-view.el b/org-ql-view.el index 8e8d40b..e44c658 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -1039,7 +1039,9 @@ current buffer. Otherwise BUFFERS-FILES is returned unchanged." (pcase (expand-files buffers-files) ((pred (seq-set-equal-p (mapcar #'expand-file-name (org-agenda-files)))) "org-agenda-files") - ((pred (seq-set-equal-p (org-ql-search-directories-files))) + ((and (guard (file-exists-p org-directory)) + (pred (seq-set-equal-p (org-ql-search-directories-files + :directories (list org-directory))))) "org-directory") (_ buffers-files))) ((pred (equal (current-buffer))) From e9815f39a071670981d2afcf4bb4b68b034a6765 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 03:16:40 -0600 Subject: [PATCH 223/560] Tests: Fix link-opening test --- tests/test-org-ql.el | 51 +++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index ee9b772..3902187 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1415,22 +1415,31 @@ RESULTS should be a list of strings as returned by (insert "* TODO Test heading\n\n") (org-mode))) - (cl-flet ((var-after-link-save-open - (var buffers-files query &key sort super-groups (input "RET")) - (org-ql-search buffers-files query - :super-groups super-groups - :sort sort :title title :buffer view-buffer) - (with-current-buffer view-buffer - (with-simulated-input input - ;; Avoid writing "Stored: ..." to test output. - (let ((inhibit-message t)) - (org-store-link nil))) - (kill-buffer)) - ;; ;; Let's see if this trick works. - (org-open-link-from-string (caar org-stored-links) nil link-buffer) - (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) - (prog1 (buffer-local-value var (current-buffer)) - (kill-buffer))))) + (cl-flet* ((open-link-in + (link buffer) + ;; Org REDUCED THE NUMBER OF ARGUMENTS TO `org-open-link-from-string'! That BREAKS BACKWARD + ;; COMPATIBILITY! So I have to make my own function so these tests can work across Org versions! + (with-current-buffer buffer + (erase-buffer) + (org-mode) + (insert link) + (backward-char 1) + (org-open-at-point))) + (var-after-link-save-open + (var buffers-files query &key sort super-groups (buffer link-buffer) (input "RET")) + (org-ql-search buffers-files query + :super-groups super-groups + :sort sort :title title :buffer view-buffer) + (with-current-buffer view-buffer + (with-simulated-input input + ;; Avoid writing "Stored: ..." to test output. + (let ((inhibit-message t)) + (org-store-link nil))) + (kill-buffer)) + (open-link-in (caar org-stored-links) buffer) + (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) + (prog1 (buffer-local-value var (current-buffer)) + (kill-buffer))))) (describe "Queries" :var ((string-query "todo:TODO regexp:heading") @@ -1465,9 +1474,6 @@ RESULTS should be a list of strings as returned by (describe "Buffers/Files" :var ((query '(and (todo "TODO") (regexp "heading"))) (one-filename (car temp-filenames))) - (it "Can search buffer containing the link" - (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query) - :to-equal link-buffer)) (it "Can search a file by filename" (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query :input "M-n M-n RET") @@ -1475,7 +1481,12 @@ RESULTS should be a list of strings as returned by (it "Can search multiple files by filename" (expect (var-after-link-save-open 'org-ql-view-buffers-files temp-filenames query :input "M-n M-n RET") - :to-equal temp-filenames))))) + :to-equal temp-filenames)) + (it "Can search buffer containing the link" + ;; This is sort-of a special case because of how the test link-opening function works. + (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query + :buffer link-buffer) + :to-equal link-buffer))))) ;; MAYBE: Also test `org-ql-views', although I already know it works now. ;; (describe "org-ql-views") From c3aa701e57c6bc3a3d7d4701c4a5d6e07de68f33 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 03:29:10 -0600 Subject: [PATCH 224/560] Tidy: Silence, Checkdoc! Some of these warnings are too much. --- org-ql-search.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index c43573d..a9fcf7d 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -334,7 +334,7 @@ For example, an org-ql dynamic block header could look like: (cl-defun org-ql-search-directories-files (&key (directories (if (file-exists-p org-directory) (list org-directory) - (user-error "org-ql-search-directories-files: No DIRECTORIES given, and `org-directory' doesn't exist"))) + (user-error "Org-ql-search-directories-files: No DIRECTORIES given, and `org-directory' doesn't exist"))) (recurse org-ql-search-directories-files-recursive) (regexp org-ql-search-directories-files-regexp)) "Return list of matching files in DIRECTORIES, a list of directory paths. From faaa6f7ee92fc33e9c873d9661a86c563bd72e86 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 03:49:15 -0600 Subject: [PATCH 225/560] Test: Tidy This prevents extra output about buffers without headings. --- tests/test-org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 3902187..9181500 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1422,6 +1422,7 @@ RESULTS should be a list of strings as returned by (with-current-buffer buffer (erase-buffer) (org-mode) + (insert "* TODO Test heading\n\n") (insert link) (backward-char 1) (org-open-at-point))) From c07971cd57782e0d6539c083c686364a1ab212a8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 03:49:46 -0600 Subject: [PATCH 226/560] Tidy: Use -let* instead of pcase-let* for plists This actually only fixes a problem with running the tests, because I don't have a way to force map-2.1 to be installed into the sandbox, so the tests on CI always fail. So for now we just use -let* for this. --- org-ql-search.el | 58 ++++++++++++++++++++++++------------------------ org-ql-view.el | 22 +++++++++--------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index a9fcf7d..e7758c7 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -272,35 +272,35 @@ Valid parameters include: For example, an org-ql dynamic block header could look like: #+BEGIN: org-ql :query (todo \"UNDERWAY\") :columns (priority todo heading) :sort (priority date) :ts-format \"%Y-%m-%d %H:%M\"" - (pcase-let* (((map :query :columns :sort :ts-format :take) params) - (query (cl-etypecase query - (string (org-ql--plain-query query)) - (t query))) - (columns (or columns '(heading todo (priority "P")))) - ;; MAYBE: Custom column functions. - (format-fns - ;; NOTE: Backquoting this alist prevents the lambdas from seeing - ;; the variable `ts-format', so we use `list' and `cons'. - (list (cons 'todo (lambda (element) - (org-element-property :todo-keyword element))) - (cons 'heading (lambda (element) - (org-make-link-string (org-element-property :raw-value element) - (org-element-property :raw-value element)))) - (cons 'priority (lambda (element) - (--when-let (org-element-property :priority element) - (char-to-string it)))) - (cons 'deadline (lambda (element) - (--when-let (org-element-property :deadline element) - (ts-format ts-format (ts-parse-org-element it))))) - (cons 'scheduled (lambda (element) - (--when-let (org-element-property :scheduled element) - (ts-format ts-format (ts-parse-org-element it))))) - (cons 'property (lambda (element property) - (org-element-property (intern (concat ":" (upcase property))) element))))) - (elements (org-ql-query :from (current-buffer) - :where query - :select '(org-element-headline-parser (line-end-position)) - :order-by sort))) + (-let* (((&plist :query :columns :sort :ts-format :take) params) + (query (cl-etypecase query + (string (org-ql--plain-query query)) + (t query))) + (columns (or columns '(heading todo (priority "P")))) + ;; MAYBE: Custom column functions. + (format-fns + ;; NOTE: Backquoting this alist prevents the lambdas from seeing + ;; the variable `ts-format', so we use `list' and `cons'. + (list (cons 'todo (lambda (element) + (org-element-property :todo-keyword element))) + (cons 'heading (lambda (element) + (org-make-link-string (org-element-property :raw-value element) + (org-element-property :raw-value element)))) + (cons 'priority (lambda (element) + (--when-let (org-element-property :priority element) + (char-to-string it)))) + (cons 'deadline (lambda (element) + (--when-let (org-element-property :deadline element) + (ts-format ts-format (ts-parse-org-element it))))) + (cons 'scheduled (lambda (element) + (--when-let (org-element-property :scheduled element) + (ts-format ts-format (ts-parse-org-element it))))) + (cons 'property (lambda (element property) + (org-element-property (intern (concat ":" (upcase property))) element))))) + (elements (org-ql-query :from (current-buffer) + :where query + :select '(org-element-headline-parser (line-end-position)) + :order-by sort))) (when take (setf elements (cl-etypecase take ((and integer (satisfies cl-minusp)) (-take-last (abs take) elements)) diff --git a/org-ql-view.el b/org-ql-view.el index e44c658..32d6866 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -550,8 +550,8 @@ dates in the past, and negative for dates in the future." (when (buffer-base-buffer b-f) (buffer-file-name (buffer-base-buffer b-f))))) (t (user-error "Only file-backed buffers can be bookmarked by Org QL View: %s" b-f))))) - (pcase-let* ((plist (org-ql-view--plist (current-buffer))) - ((map :buffers-files) plist)) + (-let* ((plist (org-ql-view--plist (current-buffer))) + ((&plist :buffers-files) plist)) ;; Replace buffers with their filenames, and signal error if any are not file-backed. (setf plist (plist-put plist :buffers-files (cl-etypecase buffers-files @@ -566,15 +566,15 @@ dates in the past, and negative for dates in the future." ;;;###autoload (defun org-ql-view-bookmark-handler (bookmark) "Show Org QL View BOOKMARK in current buffer." - ;; FIXME: Getting "(void-variable super-groups)" errors when this function is byte-compiled, - ;; but not when it's interpreted! Using (:super-groups super-groups) instead of just - ;; :super-groups fixes it, but I have no idea why, and the macroexpansion is the same. - (pcase-let* (((map org-ql-view-plist) (bookmark-get-bookmark-record bookmark)) - ((map :buffers-files :query :super-groups :narrow :sort :title) - org-ql-view-plist) - (super-groups (cl-etypecase super-groups - (symbol (symbol-value super-groups)) - (list super-groups)))) + ;; FIXME: `pcase-let*' is easier to use to destructure this, but if I use + ;; that, I want to use map 2.1 for the extra convenience, but I can't force + ;; that to be installed into the makem.sh sandbox, so I just use `-let*' here. + (-let* ((org-ql-view-plist (car (bookmark-get-bookmark-record bookmark))) + ((&plist :buffers-files :query :super-groups :narrow :sort :title) + (cdr org-ql-view-plist)) + (super-groups (cl-etypecase super-groups + (symbol (symbol-value super-groups)) + (list super-groups)))) (org-ql-search buffers-files query :super-groups super-groups :narrow narrow :sort sort :title title) ;; HACK: `bookmark--jump-via' expects that, when the handler returns, the current buffer From 5814cff18840a29a3dd08f4128b971fa50c6a778 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 03:52:26 -0600 Subject: [PATCH 227/560] Tests: (test.yml) Let lint fail Some of these lint warnings aren't going to be fixed anytime soon, and it's more useful to let the tests indicate success in that case. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c3ec60f..f9ead5f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -59,7 +59,7 @@ jobs: - name: Lint # NOTE: Uncomment this line to treat lint failures as passing # so the job doesn't show failure. - # continue-on-error: true + continue-on-error: true run: ./makem.sh -vv --sandbox=$SANDBOX_DIR lint - name: Test From 12b3b426b563627c6a1068df245b6aa86646e931 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 04:49:20 -0600 Subject: [PATCH 228/560] Tests: Call org-store-link interactively --- tests/test-org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 9181500..f1c1f25 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1435,7 +1435,7 @@ RESULTS should be a list of strings as returned by (with-simulated-input input ;; Avoid writing "Stored: ..." to test output. (let ((inhibit-message t)) - (org-store-link nil))) + (call-interactively #'org-store-link nil))) (kill-buffer)) (open-link-in (caar org-stored-links) buffer) (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) From 9396385fed8253f6378da1126ed756a44058c2ef Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 04:49:28 -0600 Subject: [PATCH 229/560] Tests: Add a couple of asserts Not absolutely needed now, but they might help in the future if something changes again. --- tests/test-org-ql.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index f1c1f25..ed3ef06 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1432,11 +1432,15 @@ RESULTS should be a list of strings as returned by :super-groups super-groups :sort sort :title title :buffer view-buffer) (with-current-buffer view-buffer + (cl-assert (member '("org-ql-search" :follow org-ql-view--link-open :store org-ql-view--link-store) + org-link-parameters) + t) (with-simulated-input input ;; Avoid writing "Stored: ..." to test output. (let ((inhibit-message t)) (call-interactively #'org-store-link nil))) (kill-buffer)) + (cl-assert (and org-stored-links (caar org-stored-links)) t) (open-link-in (caar org-stored-links) buffer) (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) (prog1 (buffer-local-value var (current-buffer)) From 673edaca11db1879d36297b96f7ea648f7125b74 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 04:52:45 -0600 Subject: [PATCH 230/560] Fix: (org-ql-view--link-open) Handle Org 9.3 links Or try to, anyway... --- org-ql-view.el | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/org-ql-view.el b/org-ql-view.el index 32d6866..10519c2 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -610,6 +610,14 @@ PATH should be the part of an \"org-ql-search:\" URL after the protocol. See, e.g. `org-ql-view--link-store'." (require 'url-parse) (require 'url-util) + (when (version<= "9.3" (org-version)) + ;; Org 9.3+ makes a backward-incompatible change to link escaping. + ;; I don't think it would be a good idea to try to guess whether + ;; the string received by this function was made with or without + ;; that change, so we'll just test the current version of Org. + ;; Any links created with older Org versions and then opened with + ;; newer ones will have to be recreated. + (setf path (url-unhex-string path))) (pcase-let* ((`(,query . ,params) (url-path-and-query (url-parse-make-urlobj "org-ql-search" nil nil nil nil path))) From badf214db7c3032052c219de5733abef83e55635 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 05:01:33 -0600 Subject: [PATCH 231/560] Tests: Adjust error message for Org 9.3 and/or Emacs 27.1 I don't know if this is due to the Org 9.3 link change or if something print/read-related changed in Emacs 27.1, but this should fix the test, hopefully on both versions. --- tests/test-org-ql.el | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index ed3ef06..be81d81 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1205,8 +1205,11 @@ RESULTS should be a list of strings as returned by (expect (open-link unquoted-lambda-link) :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: (lambda nil (error UNSAFE))"))) (it "Errors for a quoted lambda in a list" - (expect (open-link quoted-lambda-in-list-link) - :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ((quote (lambda nil (error UNSAFE))))"))) + (if (version< (org-version) "9.3") + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ((quote (lambda nil (error UNSAFE))))")) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ('(lambda nil (error UNSAFE)))")))) (it "Errors for an unquoted lambda in a list" (expect (open-link unquoted-lambda-in-list-link) :to-throw 'error '("CAUTION: Link not opened because unsafe buffers-files parameter detected: ((lambda nil (error UNSAFE)))")))) @@ -1268,8 +1271,11 @@ RESULTS should be a list of strings as returned by (expect (open-link unquoted-lambda-link) :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: (lambda (_ _) (error UNSAFE))"))) (it "Errors for a quoted lambda in a list" - (expect (open-link quoted-lambda-in-list-link) - :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ((quote (lambda (_ _) (error UNSAFE))))"))) + (if (version< (org-version) "9.3") + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ((quote (lambda (_ _) (error UNSAFE))))")) + (expect (open-link quoted-lambda-in-list-link) + :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ('(lambda (_ _) (error UNSAFE)))")))) (it "Errors for an unquoted lambda in a list" (expect (open-link unquoted-lambda-in-list-link) :to-throw 'error '("CAUTION: Link not opened because unsafe sort parameter detected: ((lambda nil (error UNSAFE)))"))))))) From 244c8290d533e5d42c8cbc2c6287889caa9e4a3e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 05:13:05 -0600 Subject: [PATCH 232/560] Notes: Update --- notes.org | 199 +++++++++++++++++++++++++++--------------------------- 1 file changed, 100 insertions(+), 99 deletions(-) diff --git a/notes.org b/notes.org index c15d42a..98cb689 100644 --- a/notes.org +++ b/notes.org @@ -1,5 +1,5 @@ #+PROPERTY: LOGGING nil -#+TODO: TODO MAYBE NEXT PROJECT UNDERWAY WAITING | DONE CANCELED +#+TODO: TODO MAYBE NEXT PROJECT UNDERWAY WAITING | DONE(d) CANCELED * [#A] Contents :PROPERTIES: @@ -23,9 +23,7 @@ #+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority todo date) :ts-format "%Y-%m-%d %H:%M" | P | M | Keyword | Heading | |---+-----+---------+------------------------------------------------| -| A | 0.5 | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | 0.5 | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | #+END: ** Underway ([[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][view]]) @@ -42,13 +40,13 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| +| A | 0.5 | TODO | [[Add Emacs 27.1 to =test.yml=][Add Emacs 27.1 to =test.yml=]] | | A | | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | 0.5 | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | -| A | 0.5 | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | | A | | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | | A | | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | | A | 0.5 | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| A | | PROJECT | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | #+END: ** Stuck projects ([[org-ql-search:(and%20(todo%20"PROJECT")%20(not%20(descendants%20(todo%20"NEXT"))))?super-groups=((:auto-parent))&sort=(priority)&title="Stuck%20Projects"][view]]) @@ -70,9 +68,8 @@ #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 | M | P | Todo | Heading | |-----+---+---------+--------------------------------------------------------------| +| 0.5 | A | TODO | [[Add Emacs 27.1 to =test.yml=][Add Emacs 27.1 to =test.yml=]] | | 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | PROJECT | [[Fix =org-ql-view--link-open= on Org 9.3+][Fix =org-ql-view--link-open= on Org 9.3+]] | -| 0.5 | A | NEXT | [[Write tests for storing/opening links][Write tests for storing/opening links]] | | 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | | 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | #+END: @@ -96,7 +93,6 @@ - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] - [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] -- [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] - [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] @@ -113,6 +109,7 @@ - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] - [[#node-caching]["Node" caching]] +- [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#helm-command][Helm command]] - [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] @@ -262,97 +259,6 @@ Eventually, the function org-export-custom-protocol-maybe is now called with a f Unfortunately it does not say what the new, required second argument is. -** PROJECT [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: -:PROPERTIES: -:milestone: 0.5 -:url: https://github.com/alphapapa/org-ql/issues/147 -:END: - -The version of Org in my personal that passes a URL-decoded string (i.e. as if run through =url-unhex-string=) as the argument to =org-ql-view--link-open=. But Org 9.3 in Emacs 27.1 passes a non-URL-decoded string, so =org-ql-view--link-open= needs to pass it through =url-unhex-string= itself. - -But I don't know which version of Org that changed in. I'm comparing the function =org-open-at-point=, but it's a 114-line function, and in neither version does it call =url-unhex-string=, so whatever code decodes the string must be elsewhere. - -I do recall something about links changing in Org 9.3 (or thereabouts), so that was probably part of it. Maybe I can find it in the release notes. I just need to know basically which version it happened in. - -I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. - -[2020-11-14 Sat 20:41] I should probably do something like this in =org-ql-view--link-open=: - -#+BEGIN_SRC elisp - (when (version<= "9.3" (org-version)) - ;; Org 9.3+ makes a backward-incompatible change to link escaping. - ;; I don't think it would be a good idea to try to guess whether - ;; the string received by this function was made with or without - ;; that change, so we'll just test the current version of Org. - ;; Any links created with older Org versions and then opened with - ;; newer ones will have to be recreated. - (setf path (url-unhex-string path))) -#+END_SRC - -But, first, I should write tests for saving and opening links, so it can actually be tested on different versions automatically. - -*** NEXT [#A] Write tests for storing/opening links -:PROPERTIES: -:milestone: 0.5 -:END: - -*** DONE [#A] Check Org release notes for link changes - -[2020-11-13 Fri 22:44] From [[https://www.orgmode.org/Changes_old.html][the changelog]]: - -#+BEGIN_QUOTE -Change bracket link escaping syntax - -Org used to percent-encode sensitive characters in the URI part of the bracket links. - -Now, escaping mechanism uses the usual backslash character, according to the following rules, applied in order: - -- All consecutive \ characters at the end of the link must be escaped; -- Any ] character at the very end of the link must be escaped; -- All consecutive \ characters preceding ][ or ]] patterns must be escaped; -- Any ] character followed by either [ or ] must be escaped; -- Others ] and \ characters need not be escaped. - -When in doubt, use the function org-link-escape in order to turn a link string into its properly escaped form. - -The following function will help switching your links to the new syntax: - -(defun org-update-link-syntax (&optional no-query) - "Update syntax for links in current buffer. -Query before replacing a link, unless optional argument NO-QUERY -is non-nil." - (interactive "P") - (org-with-point-at 1 - (let ((case-fold-search t)) - (while (re-search-forward "\\[\\[[^]]*?%\\(?:2[05]\\|5[BD]\\)" nil t) - (let ((object (save-match-data (org-element-context)))) - (when (and (eq 'link (org-element-type object)) - (= (match-beginning 0) - (org-element-property :begin object))) - (goto-char (org-element-property :end object)) - (let* ((uri-start (+ 2 (match-beginning 0))) - (uri-end (save-excursion - (goto-char uri-start) - (re-search-forward "\\][][]" nil t) - (match-beginning 0))) - (uri (buffer-substring-no-properties uri-start uri-end))) - (when (or no-query - (y-or-n-p - (format "Possibly obsolete URI syntax: %S. Fix? " - uri))) - (setf (buffer-substring uri-start uri-end) - (org-link-escape (org-link-decode uri))))))))))) - -The old org-link-escape and org-link-unescape functions have been renamed into org-link-encode and org-link-decode. -#+END_QUOTE - -This is exactly the kind of breaking, backwards-incompatible change that I've said should mandate a major-version increment. It's not only a change in Org's code, and a change that affects third-party packages, but it's a change in the file format! - -Is it even possible to support both Org 9.3+ and earlier versions at the same time? - -This change doesn't even seem to make sense to me. Percent-encoding solves so many problems in a simple way: pass a string to the encoding function on the way in, and to the decoding function on the way out. Now, instead of a simple, standard way of encoding links, there's a list of Org-specific rules and Org-specific encoding/decoding functions. What is gained this way? - - ** PROJECT [#A] Convert simple sexp queries to non-sexp [2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... @@ -1495,6 +1401,101 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** DONE [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: +:PROPERTIES: +:milestone: 0.5 +:url: https://github.com/alphapapa/org-ql/issues/147 +:END: + +The version of Org in my personal that passes a URL-decoded string (i.e. as if run through =url-unhex-string=) as the argument to =org-ql-view--link-open=. But Org 9.3 in Emacs 27.1 passes a non-URL-decoded string, so =org-ql-view--link-open= needs to pass it through =url-unhex-string= itself. + +But I don't know which version of Org that changed in. I'm comparing the function =org-open-at-point=, but it's a 114-line function, and in neither version does it call =url-unhex-string=, so whatever code decodes the string must be elsewhere. + +I do recall something about links changing in Org 9.3 (or thereabouts), so that was probably part of it. Maybe I can find it in the release notes. I just need to know basically which version it happened in. + +I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. + +[2020-11-14 Sat 20:41] I should probably do something like this in =org-ql-view--link-open=: + +#+BEGIN_SRC elisp + (when (version<= "9.3" (org-version)) + ;; Org 9.3+ makes a backward-incompatible change to link escaping. + ;; I don't think it would be a good idea to try to guess whether + ;; the string received by this function was made with or without + ;; that change, so we'll just test the current version of Org. + ;; Any links created with older Org versions and then opened with + ;; newer ones will have to be recreated. + (setf path (url-unhex-string path))) +#+END_SRC + +But, first, I should write tests for saving and opening links, so it can actually be tested on different versions automatically. + +[2020-11-16 Mon 05:12] Finally, all of the tests pass on my Org version and on 9.3. And I tested for all the combinations of link and bookmark saving/opening I could think of. I hope they work and are safe. + +*** DONE [#A] Write tests for storing/opening links +:PROPERTIES: +:milestone: 0.5 +:END: + +[2020-11-16 Mon 05:11] Took way longer than I expected. I hope it was worth it. + +*** DONE [#A] Check Org release notes for link changes + +[2020-11-13 Fri 22:44] From [[https://www.orgmode.org/Changes_old.html][the changelog]]: + +#+BEGIN_QUOTE +Change bracket link escaping syntax + +Org used to percent-encode sensitive characters in the URI part of the bracket links. + +Now, escaping mechanism uses the usual backslash character, according to the following rules, applied in order: + +- All consecutive \ characters at the end of the link must be escaped; +- Any ] character at the very end of the link must be escaped; +- All consecutive \ characters preceding ][ or ]] patterns must be escaped; +- Any ] character followed by either [ or ] must be escaped; +- Others ] and \ characters need not be escaped. + +When in doubt, use the function org-link-escape in order to turn a link string into its properly escaped form. + +The following function will help switching your links to the new syntax: + +(defun org-update-link-syntax (&optional no-query) + "Update syntax for links in current buffer. +Query before replacing a link, unless optional argument NO-QUERY +is non-nil." + (interactive "P") + (org-with-point-at 1 + (let ((case-fold-search t)) + (while (re-search-forward "\\[\\[[^]]*?%\\(?:2[05]\\|5[BD]\\)" nil t) + (let ((object (save-match-data (org-element-context)))) + (when (and (eq 'link (org-element-type object)) + (= (match-beginning 0) + (org-element-property :begin object))) + (goto-char (org-element-property :end object)) + (let* ((uri-start (+ 2 (match-beginning 0))) + (uri-end (save-excursion + (goto-char uri-start) + (re-search-forward "\\][][]" nil t) + (match-beginning 0))) + (uri (buffer-substring-no-properties uri-start uri-end))) + (when (or no-query + (y-or-n-p + (format "Possibly obsolete URI syntax: %S. Fix? " + uri))) + (setf (buffer-substring uri-start uri-end) + (org-link-escape (org-link-decode uri))))))))))) + +The old org-link-escape and org-link-unescape functions have been renamed into org-link-encode and org-link-decode. +#+END_QUOTE + +This is exactly the kind of breaking, backwards-incompatible change that I've said should mandate a major-version increment. It's not only a change in Org's code, and a change that affects third-party packages, but it's a change in the file format! + +Is it even possible to support both Org 9.3+ and earlier versions at the same time? + +This change doesn't even seem to make sense to me. Percent-encoding solves so many problems in a simple way: pass a string to the encoding function on the way in, and to the decoding function on the way out. Now, instead of a simple, standard way of encoding links, there's a list of Org-specific rules and Org-specific encoding/decoding functions. What is gained this way? + + ** DONE [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: :PROPERTIES: :milestone: 0.5 From ec0f8c7231132056842941d1b8ac7baea3cf4026 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 05:16:56 -0600 Subject: [PATCH 233/560] Meta: Update makem.sh, Makefile, test.yml --- .github/workflows/test.yml | 8 ++++++-- Makefile | 3 ++- makem.sh | 3 ++- notes.org | 16 ++++++++-------- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f9ead5f..0b274ed 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,9 @@ # * test.yml --- Test Emacs packages using makem.sh on GitHub Actions -# https://github.com/alphapapa/makem.sh +# URL: https://github.com/alphapapa/makem.sh +# Version: 0.2 + +# * Commentary: # Based on Steve Purcell's examples at # , @@ -39,6 +42,7 @@ jobs: matrix: emacs_version: - 26.3 + - 27.1 - snapshot steps: - uses: purcell/setup-emacs@master @@ -50,7 +54,7 @@ jobs: - name: Initialize sandbox run: | SANDBOX_DIR=$(mktemp -d) || exit 1 - echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR + echo "SANDBOX_DIR=$SANDBOX_DIR" >> $GITHUB_ENV ./makem.sh -vv --sandbox=$SANDBOX_DIR --install-deps --install-linters # The "all" rule is not used, because it treats compilation warnings diff --git a/Makefile b/Makefile index 17abfe0..68906e9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ # * makem.sh/Makefile --- Script to aid building and testing Emacs Lisp packages -# This Makefile is from the makem.sh repo: . +# URL: https://github.com/alphapapa/makem.sh +# Version: 0.2 # * Arguments diff --git a/makem.sh b/makem.sh index d110e2c..2d710a3 100755 --- a/makem.sh +++ b/makem.sh @@ -2,7 +2,8 @@ # * makem.sh --- Script to aid building and testing Emacs Lisp packages -# https://github.com/alphapapa/makem.sh +# URL: https://github.com/alphapapa/makem.sh +# Version: 0.2 # * Commentary: diff --git a/notes.org b/notes.org index 98cb689..f8b5d9d 100644 --- a/notes.org +++ b/notes.org @@ -40,7 +40,6 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| -| A | 0.5 | TODO | [[Add Emacs 27.1 to =test.yml=][Add Emacs 27.1 to =test.yml=]] | | A | | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | | A | | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | @@ -68,7 +67,6 @@ #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 | M | P | Todo | Heading | |-----+---+---------+--------------------------------------------------------------| -| 0.5 | A | TODO | [[Add Emacs 27.1 to =test.yml=][Add Emacs 27.1 to =test.yml=]] | | 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | | 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | | 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | @@ -79,7 +77,6 @@ :TOC: :include descendants :depth 1 :END: :CONTENTS: -- [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] @@ -109,6 +106,7 @@ - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] - [[#node-caching]["Node" caching]] +- [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] - [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] - [[#helm-command][Helm command]] @@ -120,11 +118,6 @@ - [[#use-macros-for-date][Use macros for date]] :END: -** TODO [#A] Add Emacs 27.1 to =test.yml= -:PROPERTIES: -:milestone: 0.5 -:END: - ** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. @@ -1401,6 +1394,13 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** DONE [#A] Add Emacs 27.1 to =test.yml= +:PROPERTIES: +:milestone: 0.5 +:END: + +[2020-11-16 Mon 05:22] Also releasing =makem.sh= 0.2 with this change. + ** DONE [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: :PROPERTIES: :milestone: 0.5 From 2c14903c7654fddeedf387937607aa2e1baaea60 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 05:50:37 -0600 Subject: [PATCH 234/560] Notes: Update --- notes.org | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/notes.org b/notes.org index f8b5d9d..1f87eb7 100644 --- a/notes.org +++ b/notes.org @@ -40,26 +40,26 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| -| A | | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | +| A | 0.5 | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| A | | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| A | 0.5 | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| A | 0.5 | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | | A | 0.5 | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | | A | | PROJECT | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | #+END: -** Stuck projects ([[org-ql-search:(and%20(todo%20"PROJECT")%20(not%20(descendants%20(todo%20"NEXT"))))?super-groups=((:auto-parent))&sort=(priority)&title="Stuck%20Projects"][view]]) +** Stuck projects ([[org-ql-search:%2528and%2520%2528todo%2520%2522PROJECT%2522%2529%2520%2528not%2520%2528descendants%2520%2528todo%2520%2522NEXT%2522%2529%2529%2529%2529?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Stuck%2520Projects%2522][view]]) #+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns (((property "milestone") "M") (priority "P") heading) :sort (priority date) :take 7 | M | P | Heading | |-----+---+-------------------------------------------------------| | 0.5 | A | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| | A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| | A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| 0.5 | A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| 0.5 | A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | | | A | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | | | B | [[Move this notes file into an orphan =meta/notes= branch][Move this notes file into an orphan =meta/notes= branch]] | | | B | [[Outline path predicate][Outline path predicate]] | -| | B | [[Group tag support][Group tag support]] | +| 0.6 | B | [[Group tag support][Group tag support]] | #+END: ** Milestones ([[org-ql-search:todo:?super-groups=((:auto-property%20"milestone"))&sort=(todo)&title="Milestones"][view]]) @@ -67,8 +67,12 @@ #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 | M | P | Todo | Heading | |-----+---+---------+--------------------------------------------------------------| +| 0.5 | A | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | | 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | | 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | | 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | #+END: @@ -220,6 +224,9 @@ I should benchmark it to see how much difference it makes, because all those ~fs However, there might still be a useful idea here somewhere... ** MAYBE [#C] Alternative parsing libraries +:PROPERTIES: +:milestone: future +:END: + e.g. Bovine and Wisent come with Emacs, which would allow us to drop the =peg= dependency (which doesn't use lexical binding). + [[https://github.com/cute-jumper/parsec.el][parsec]] is third-party, but looks powerful @@ -229,6 +236,9 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. ** NEXT [#A] Make dynamic blocks warn about sexp queries +:PROPERTIES: +:milestone: 0.5 +:END: [2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. @@ -253,6 +263,9 @@ Unfortunately it does not say what the new, required second argument is. ** PROJECT [#A] Convert simple sexp queries to non-sexp +:PROPERTIES: +:milestone: 0.5 +:END: [2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... @@ -357,6 +370,7 @@ Maybe make it an option to automatically convert them when possible, because if ** PROJECT [#A] Checking links for unsafe parameters :PROPERTIES: :ID: ba70e375-eddb-40df-8892-fb418c1f70d1 +:milestone: 0.5 :END: :LOGBOOK: - State "PROJECT" from "UNDERWAY" [2020-11-12 Thu 00:26] @@ -644,6 +658,9 @@ That seems to work, like: *** DONE Save query from ql-agenda buffer ** PROJECT [#B] Group tag support +:PROPERTIES: +:milestone: 0.6 +:END: *** UNDERWAY Benchmarking tags searches without and with new group-tags support @@ -1138,6 +1155,9 @@ One of the things in that branch is =org-ql-item=, which is a struct used to car Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. *** MAYBE [#C] Experiment with =widget= +:PROPERTIES: +:milestone: future +:END: The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. @@ -4205,6 +4225,6 @@ I don't need this right now, but it might come in handy here or elsewhere. ** File-local variables # Local Variables: -# before-save-hook: ((lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o))))) org-make-toc) +# before-save-hook: ((lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o))))) org-update-all-dblocks org-make-toc) # End: From 2a010f29c18a32ebe1d71d56ce76d0b1631838c9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 20:08:44 -0600 Subject: [PATCH 235/560] Fix: (org-dblock-write:org-ql) Use org-link-display-format Fixes #153. Thanks to @jbriquet for reporting. --- org-ql-search.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index e7758c7..9f555ce 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -285,7 +285,8 @@ For example, an org-ql dynamic block header could look like: (org-element-property :todo-keyword element))) (cons 'heading (lambda (element) (org-make-link-string (org-element-property :raw-value element) - (org-element-property :raw-value element)))) + (org-link-display-format + (org-element-property :raw-value element))))) (cons 'priority (lambda (element) (--when-let (org-element-property :priority element) (char-to-string it)))) From 50ba4414155a27d33c4c1a31de8b2f9fb90ad669 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 21:16:09 -0600 Subject: [PATCH 236/560] Fix: (org-ql-view-bookmark-handler) Bookmark destructuring See #147. Thanks to @tpeacock19 for reporting. --- org-ql-view.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 10519c2..29e5499 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -569,9 +569,10 @@ dates in the past, and negative for dates in the future." ;; FIXME: `pcase-let*' is easier to use to destructure this, but if I use ;; that, I want to use map 2.1 for the extra convenience, but I can't force ;; that to be installed into the makem.sh sandbox, so I just use `-let*' here. - (-let* ((org-ql-view-plist (car (bookmark-get-bookmark-record bookmark))) + (-let* ((record (bookmark-get-bookmark-record bookmark)) + ((&alist 'org-ql-view-plist) record) ((&plist :buffers-files :query :super-groups :narrow :sort :title) - (cdr org-ql-view-plist)) + org-ql-view-plist) (super-groups (cl-etypecase super-groups (symbol (symbol-value super-groups)) (list super-groups)))) From d73d28f4c3a8f27c985015ef38d171e0295693c5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 22:13:23 -0600 Subject: [PATCH 237/560] Notes: Add idea --- notes.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/notes.org b/notes.org index 1f87eb7..76c4ddf 100644 --- a/notes.org +++ b/notes.org @@ -89,6 +89,7 @@ - [[#partial-match-for-property-queries][Partial match for property queries]] - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] +- [[#org-ql-block-let-org-agenda-format-its-output][org-ql-block: Let org-agenda format its output]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] @@ -215,6 +216,10 @@ I should benchmark it to see how much difference it makes, because all those ~fs ** TODO [#C] Update commentary +** MAYBE org-ql-block: Let org-agenda format its output + +[2020-11-16 Mon 22:12] As suggested by Kevin J. Foley. See [[https://github.com/alphapapa/org-ql/pull/113#issuecomment-728674220][#113]]. It might actually be simple to do and might work very well. + ** MAYBE [#C] Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. From 0ca6b4b119992f79104671fe0dc62072ee200ab8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 23:51:24 -0600 Subject: [PATCH 238/560] Tidy: Docstring --- org-ql-search.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-search.el b/org-ql-search.el index 9f555ce..8a012be 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -243,7 +243,7 @@ automatically from the query." "Insert content for org-ql dynamic block at point according to PARAMS. Valid parameters include: - :query An Org QL query expression in either sexp or non-sexp + :query An Org QL query expression in either sexp or string form. :columns A list of columns, including `heading', `todo', From 71703def0406da8df12f435a752b4e5eb57dd250 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 16 Nov 2020 23:52:15 -0600 Subject: [PATCH 239/560] Change: Query safety checks - Variable org-ql-ask-unsafe-queries replaces org-ql-view-ask-unsafe-links. - New function: org-ql--ask-unsafe-query. - Tests: Improve --- org-ql-search.el | 4 ++- org-ql-view.el | 33 +++---------------------- org-ql.el | 31 +++++++++++++++++++++++ tests/test-org-ql.el | 58 +++++++++++++++++++++++++++++++++----------- 4 files changed, 82 insertions(+), 44 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index 8a012be..145b37c 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -275,7 +275,9 @@ For example, an org-ql dynamic block header could look like: (-let* (((&plist :query :columns :sort :ts-format :take) params) (query (cl-etypecase query (string (org-ql--plain-query query)) - (t query))) + (list ;; SAFETY: Query is in sexp form: ask for confirmation, because it could contain arbitrary code. + (org-ql--ask-unsafe-query query) + query))) (columns (or columns '(heading todo (priority "P")))) ;; MAYBE: Custom column functions. (format-fns diff --git a/org-ql-view.el b/org-ql-view.el index 29e5499..089baf6 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -97,23 +97,6 @@ Based on `org-agenda-mode-map'.") "Options for `org-ql-view'." :group 'org-ql) -(defcustom org-ql-view-ask-unsafe-links t - "Ask before opening a link that could run arbitrary code. -Org QL queries in sexp form can contain arbitrary expressions. -When opening an \"org-ql-search:\" link that contains a query in -sexp form, and this option is non-nil, the user will be prompted -for confirmation before opening the link. - -This variable may be set file-locally to disable this warning in -files that the user assumes are safe (e.g. of known provenance). -Users who are entirely unconcerned about this issue may disable -the option globally (at their own risk, however minimal it -probably is). - -See Info node `(org-ql)Queries'." - :type 'boolean - :risky t) - (defcustom org-ql-view-display-buffer-action nil "Action argument passed through `pop-to-buffer' to `display-buffer', which see." :type '(cons function alist)) @@ -644,18 +627,10 @@ protocol. See, e.g. `org-ql-view--link-store'." (stringp buffers-files) (cl-every #'stringp buffers-files)) (error "CAUTION: Link not opened because unsafe buffers-files parameter detected: %s" buffers-files)) - (when (and org-ql-view-ask-unsafe-links - (or (string-match (rx bol (0+ space) "(") query) - (listp query))) - ;; Query is in sexp form: ask for confirmation, because it could contain arbitrary code. - (let ((query-string (propertize (cl-etypecase query - (list (prin1-to-string query)) - (string query)) - ;; FIXME: The face doesn't seem to be displayed. - 'face 'font-lock-warning-face))) - (unless (yes-or-no-p (concat "Query is in sexp form and could contain arbitrary code: " - query-string " Execute it? ")) - (user-error "Query aborted by user")))) + (when (or (listp query) + (string-match (rx bol (0+ space) "(") query)) + ;; SAFETY: Query is in sexp form: ask for confirmation, because it could contain arbitrary code. + (org-ql--ask-unsafe-query query)) (org-ql-search buffers-files query :sort sort :super-groups groups diff --git a/org-ql.el b/org-ql.el index 3b97307..c479161 100644 --- a/org-ql.el +++ b/org-ql.el @@ -137,6 +137,24 @@ This list should not contain any duplicates.")) ;; TODO: Add info manual link. :link '(url-link "https://github.com/alphapapa/org-ql")) +(defcustom org-ql-ask-unsafe-queries t + "Ask before running a query that could run arbitrary code. +Org QL queries in sexp form can contain arbitrary expressions. +When opening an \"org-ql-search:\" link or updating a dynamic +block that contains a query in sexp form, and this option is +non-nil, the user will be prompted for confirmation before +opening the link. + +This variable may be set file-locally to disable this warning in +files that the user assumes are safe (e.g. of known provenance). +Users who are entirely unconcerned about this issue may disable +the option globally (at their own risk, however minimal it +probably is). + +See Info node `(org-ql)Queries'." + :type 'boolean + :risky t) + ;;;; Macros (cl-defmacro org-ql--defpred (name args docstring &rest body) @@ -531,6 +549,19 @@ from within ELEMENT's buffer." (setf (cadr element) properties) element)) +(defun org-ql--ask-unsafe-query (query) + "Signal an error if user rejects running QUERY. +If `org-ql-view-ask-unsafe-links' is nil, does nothing and +returns nil." + (when org-ql-ask-unsafe-queries + (let ((query-string (propertize (cl-etypecase query + (list (prin1-to-string query)) + (string query)) + 'face 'font-lock-warning-face))) + (unless (yes-or-no-p (concat "Query is in sexp form and could contain arbitrary code: " + query-string " Execute it? ")) + (user-error "Query aborted by user"))))) + ;;;;; Query processing ;; Processing, compiling, etc. for queries. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index be81d81..e1c40d5 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1422,7 +1422,7 @@ RESULTS should be a list of strings as returned by (org-mode))) (cl-flet* ((open-link-in - (link buffer) + (link buffer input) ;; Org REDUCED THE NUMBER OF ARGUMENTS TO `org-open-link-from-string'! That BREAKS BACKWARD ;; COMPATIBILITY! So I have to make my own function so these tests can work across Org versions! (with-current-buffer buffer @@ -1431,9 +1431,12 @@ RESULTS should be a list of strings as returned by (insert "* TODO Test heading\n\n") (insert link) (backward-char 1) - (org-open-at-point))) + (with-simulated-input input + (org-open-at-point)))) + (var-after-link-save-open - (var buffers-files query &key sort super-groups (buffer link-buffer) (input "RET")) + (var buffers-files query &key sort super-groups + (buffer link-buffer) (store-input "RET") open-input) (org-ql-search buffers-files query :super-groups super-groups :sort sort :title title :buffer view-buffer) @@ -1441,26 +1444,53 @@ RESULTS should be a list of strings as returned by (cl-assert (member '("org-ql-search" :follow org-ql-view--link-open :store org-ql-view--link-store) org-link-parameters) t) - (with-simulated-input input + (with-simulated-input store-input ;; Avoid writing "Stored: ..." to test output. (let ((inhibit-message t)) (call-interactively #'org-store-link nil))) (kill-buffer)) (cl-assert (and org-stored-links (caar org-stored-links)) t) - (open-link-in (caar org-stored-links) buffer) + (open-link-in (caar org-stored-links) buffer open-input) (with-current-buffer (get-buffer (concat "*Org QL View: " title "*")) (prog1 (buffer-local-value var (current-buffer)) (kill-buffer))))) (describe "Queries" :var ((string-query "todo:TODO regexp:heading") - (sexp-query '(and (todo "TODO") (regexp "heading")))) - (it "Sexps match" - (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query) :to-equal sexp-query)) - (it "Strings match" - ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. - (expect (var-after-link-save-open 'org-ql-view-query temp-filenames string-query) - :to-equal sexp-query))) + (string-query-in-sexp-form '(and (todo "TODO") (regexp "heading"))) + ;; NOTE: The sexp query must be one that `org-ql--query-sexp-to-string' + ;; can't convert to a string. + (sexp-query '(or (todo "TODO") (regexp "heading")))) + + (describe "in sexp form" + + (describe "prompt when `org-ql-ask-unsafe-queries' is non-nil" + :var ((org-ql-ask-unsafe-queries t)) + + (it "and signal an error when rejected by user" + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query + :open-input "no RET") + :to-throw 'user-error '("Query aborted by user"))) + (it "and run when approved by user" + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query + :open-input "yes RET") + :to-equal sexp-query))) + + (it "don't prompt when `org-ql-ask-unsafe-queries' is nil" + (let ((org-ql-ask-unsafe-queries nil)) + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query) + :to-equal sexp-query))) + + (it "match after restoring" + (let ((org-ql-ask-unsafe-queries nil)) ; Disable safety check for this test. + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query) + :to-equal sexp-query)))) + + (describe "in string form" + (it "match after restoring" + ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. + (expect (var-after-link-save-open 'org-ql-view-query temp-filenames string-query) + :to-equal string-query-in-sexp-form)))) (describe "Grouping" :var ((query '(and (todo "TODO") (regexp "heading"))) @@ -1487,11 +1517,11 @@ RESULTS should be a list of strings as returned by (one-filename (car temp-filenames))) (it "Can search a file by filename" (expect (var-after-link-save-open 'org-ql-view-buffers-files one-filename query - :input "M-n M-n RET") + :store-input "M-n M-n RET") :to-equal one-filename)) (it "Can search multiple files by filename" (expect (var-after-link-save-open 'org-ql-view-buffers-files temp-filenames query - :input "M-n M-n RET") + :store-input "M-n M-n RET") :to-equal temp-filenames)) (it "Can search buffer containing the link" ;; This is sort-of a special case because of how the test link-opening function works. From a02514c0dc8dfef1e8425a93cd23d91e72fbc1d5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 17 Nov 2020 00:24:26 -0600 Subject: [PATCH 240/560] Tests: Test dynamic block sexp query warning --- tests/test-org-ql.el | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index e1c40d5..7dad757 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1406,6 +1406,34 @@ RESULTS should be a list of strings as returned by (mapcar #'find-file-noselect temp-filenames) query) :to-equal temp-filenames))))) + (describe "Dynamic blocks" + (describe "warn about sexp queries" + + (cl-flet ((test-dblock + (&optional input) (with-current-buffer (get-buffer-create "*TEST DBLOCK*") + (erase-buffer) + (org-mode) + (insert "* TODO Heading 1\n\n" + "#+BEGIN: org-ql :query (or (todo) (regexp \"Heading\")) :columns (todo)\n" + "#+END:") + (goto-char (point-min)) + (forward-line 2) + (with-simulated-input input + (org-dblock-update)) + (kill-buffer)))) + + (it "when org-ql-ask-unsafe-queries is non-nil" + ;; TODO: Should the query be converted to string form if possible and only warn if not? + (let ((org-ql-ask-unsafe-queries t)) + (expect (test-dblock "no RET") + :to-throw 'user-error '("Query aborted by user")))) + + (it "unless org-ql-ask-unsafe-queries is nil" + ;; TODO: Should the query be converted to string form if possible and only warn if not? + (let ((org-ql-ask-unsafe-queries nil)) + (expect (test-dblock) + :not :to-throw)))))) + (describe "Links" ;; Not sure if this binding works. :var ((title "ORG-QL-TEST") From 814f3f0edaf2cfd4a29d3ea98a6dc767e9651217 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 17 Nov 2020 00:25:34 -0600 Subject: [PATCH 241/560] Notes: Update --- notes.org | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/notes.org b/notes.org index 76c4ddf..6dfba38 100644 --- a/notes.org +++ b/notes.org @@ -40,7 +40,6 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| -| A | 0.5 | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | | A | 0.5 | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | | A | 0.5 | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | @@ -65,15 +64,15 @@ ** Milestones ([[org-ql-search:todo:?super-groups=((:auto-property%20"milestone"))&sort=(todo)&title="Milestones"][view]]) #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|-----+---+---------+--------------------------------------------------------------| -| 0.5 | A | NEXT | [[Make dynamic blocks warn about sexp queries][Make dynamic blocks warn about sexp queries]] | -| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | -| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | -| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | +| M | P | Todo | Heading | +|--------+---+---------+--------------------------------------------------------------| +| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | +| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | +| future | C | MAYBE | [[Alternative parsing libraries][Alternative parsing libraries]] | #+END: * [#A] Tasks @@ -93,7 +92,6 @@ - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] -- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] - [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] - [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] @@ -111,6 +109,7 @@ - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] - [[#node-caching]["Node" caching]] +- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] - [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] - [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] @@ -240,13 +239,6 @@ However, there might still be a useful idea here somewhere... When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. -** NEXT [#A] Make dynamic blocks warn about sexp queries -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. - ** PROJECT [#A] Compatibility with Org 9.4 custom link changes :bug: :PROPERTIES: :milestone: 0.5 @@ -1419,6 +1411,18 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** DONE [#A] Make dynamic blocks warn about sexp queries +:PROPERTIES: +:milestone: 0.5 +:END: +:LOGBOOK: +CLOCK: [2020-11-16 Mon 22:56]--[2020-11-17 Tue 00:25] => 1:29 +:END: + +[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. + +[2020-11-17 Tue 00:25] It warns and the warning is tested. + ** DONE [#A] Add Emacs 27.1 to =test.yml= :PROPERTIES: :milestone: 0.5 From 619fd8c403da93bc204bd0ae58ddd52c7678cda5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 17 Nov 2020 00:35:53 -0600 Subject: [PATCH 242/560] Notes: Update --- notes.org | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/notes.org b/notes.org index 6dfba38..74f0331 100644 --- a/notes.org +++ b/notes.org @@ -23,12 +23,13 @@ #+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority todo date) :ts-format "%Y-%m-%d %H:%M" | P | M | Keyword | Heading | |---+-----+---------+------------------------------------------------| +| A | 0.5 | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | #+END: ** Underway ([[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][view]]) -#+BEGIN: org-ql :query (todo "UNDERWAY") :columns (((property "milestone") "M") (priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" +#+BEGIN: org-ql :query "todo:UNDERWAY" :columns (((property "milestone") "M") (priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" | M | P | Keyword | Heading | |---+---+----------+--------------------------------------------------------------------| | | B | UNDERWAY | [["Node" caching]["Node" caching]] | @@ -40,6 +41,7 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| +| A | 0.5 | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | | A | 0.5 | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | | A | 0.5 | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | @@ -61,18 +63,18 @@ | 0.6 | B | [[Group tag support][Group tag support]] | #+END: -** Milestones ([[org-ql-search:todo:?super-groups=((:auto-property%20"milestone"))&sort=(todo)&title="Milestones"][view]]) +** Milestones ([[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528todo%2529&title=%2522Milestones%2522][view]]) #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|--------+---+---------+--------------------------------------------------------------| -| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | -| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | -| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | -| future | C | MAYBE | [[Alternative parsing libraries][Alternative parsing libraries]] | +| M | P | Todo | Heading | +|-----+---+---------+--------------------------------------------------------------| +| 0.5 | A | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | +| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | +| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | #+END: * [#A] Tasks @@ -80,6 +82,7 @@ :TOC: :include descendants :depth 1 :END: :CONTENTS: +- [[#views-multiple-sorters-are-not-preserved][Views: Multiple sorters are not preserved]] - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] @@ -122,6 +125,12 @@ - [[#use-macros-for-date][Use macros for date]] :END: +** TODO [#A] Views: Multiple sorters are not preserved :bug: +:PROPERTIES: +:milestone: 0.5 +:url: https://github.com/alphapapa/org-ql/issues/136 +:END: + ** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. @@ -4235,5 +4244,6 @@ I don't need this right now, but it might come in handy here or elsewhere. # Local Variables: # before-save-hook: ((lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o))))) org-update-all-dblocks org-make-toc) +# org-ql-ask-unsafe-queries: nil # End: From d500d28af53b479de23140908b68658475758c14 Mon Sep 17 00:00:00 2001 From: Imran Khan Date: Sun, 23 Aug 2020 00:20:16 +0600 Subject: [PATCH 243/560] Change nreverse to non-destructive version --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index f7efbbf..a2d3198 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1456,7 +1456,7 @@ PREDICATES is a list of one or more sorting methods, including: ;; Put at end of list if not found (1+ (length org-todo-keywords-1))))))) (-flatten-n 1 (-map #'cdr sorted-groups))))) - (cl-loop for pred in (nreverse predicates) + (cl-loop for pred in (reverse predicates) do (setq items (if (eq pred 'todo) (sort-by-todo-keyword items) (-sort (sorter pred) items))) From 6618318622c0b49dc0c22eb21dd74a33b425e574 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 18 Nov 2020 00:03:41 -0600 Subject: [PATCH 244/560] Update readme, version header --- README.org | 5 +++++ org-ql.el | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 23c4a9d..9b6b5d7 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.8 + +*Fixed* ++ Multiple sorters not preserved when refreshing views. (Fixes [[https://github.com/alphapapa/org-ql/issues/136][#136]], [[https://github.com/alphapapa/org-ql/pull/137][#137]]. Thanks to [[https://github.com/natrys][Imran Khan]].) + ** 0.4.7 *Fixed* diff --git a/org-ql.el b/org-ql.el index a2d3198..85b47cd 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.6 +;; Version: 0.4.8 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda From a9c734506677b66b544a4aa4e31cac5050a20134 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 18 Nov 2020 03:04:34 -0600 Subject: [PATCH 245/560] Notes: Add idea --- notes.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/notes.org b/notes.org index 74f0331..a04c989 100644 --- a/notes.org +++ b/notes.org @@ -92,6 +92,7 @@ - [[#org-agenda-skip-function][org-agenda-skip-function]] - [[#update-commentary][Update commentary]] - [[#org-ql-block-let-org-agenda-format-its-output][org-ql-block: Let org-agenda format its output]] +- [[#omnifocus-like-screencasts][OmniFocus-like screencasts]] - [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] - [[#alternative-parsing-libraries][Alternative parsing libraries]] - [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] @@ -228,6 +229,10 @@ I should benchmark it to see how much difference it makes, because all those ~fs [2020-11-16 Mon 22:12] As suggested by Kevin J. Foley. See [[https://github.com/alphapapa/org-ql/pull/113#issuecomment-728674220][#113]]. It might actually be simple to do and might work very well. +** MAYBE OmniFocus-like screencasts + +[2020-11-18 Wed 03:03] Looking at OmniFocus's web site now, their short videos showing features demonstrate a lot of features that exist in org-ql already. After implementing section-based views, it would be cool to make some short demos showing similar features. + ** MAYBE [#C] Overlay-based caching inspired by org-num-mode [2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. From 6b96c3684ded8650981b99f3a0427c13d3dba07a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 18 Nov 2020 04:16:07 -0600 Subject: [PATCH 246/560] Notes: Update --- notes.org | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/notes.org b/notes.org index a04c989..95dc303 100644 --- a/notes.org +++ b/notes.org @@ -23,7 +23,6 @@ #+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority todo date) :ts-format "%Y-%m-%d %H:%M" | P | M | Keyword | Heading | |---+-----+---------+------------------------------------------------| -| A | 0.5 | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | #+END: @@ -41,7 +40,6 @@ #+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 | P | M | Todo | Heading | |---+-----+---------+--------------------------------------------------------------| -| A | 0.5 | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | | A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | | A | 0.5 | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | | A | 0.5 | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | @@ -66,15 +64,15 @@ ** Milestones ([[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528todo%2529&title=%2522Milestones%2522][view]]) #+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|-----+---+---------+--------------------------------------------------------------| -| 0.5 | A | TODO | [[Views: Multiple sorters are not preserved][Views: Multiple sorters are not preserved]] | -| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | -| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | -| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | +| M | P | Todo | Heading | +|--------+---+---------+--------------------------------------------------------------| +| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | +| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | +| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | +| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | +| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | +| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | +| future | C | MAYBE | [[Alternative parsing libraries][Alternative parsing libraries]] | #+END: * [#A] Tasks @@ -82,7 +80,6 @@ :TOC: :include descendants :depth 1 :END: :CONTENTS: -- [[#views-multiple-sorters-are-not-preserved][Views: Multiple sorters are not preserved]] - [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] - [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] - [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] @@ -113,6 +110,7 @@ - [[#update-view-screenshots][Update view screenshots]] - [[#test-caching][Test caching]] - [[#node-caching]["Node" caching]] +- [[#views-multiple-sorters-are-not-preserved][Views: Multiple sorters are not preserved]] - [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] - [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] - [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] @@ -126,12 +124,6 @@ - [[#use-macros-for-date][Use macros for date]] :END: -** TODO [#A] Views: Multiple sorters are not preserved :bug: -:PROPERTIES: -:milestone: 0.5 -:url: https://github.com/alphapapa/org-ql/issues/136 -:END: - ** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate It should act like ~(or (deadline auto) (scheduled :to today))~. @@ -1425,6 +1417,12 @@ This works okay (except the priority accessor needs to be fixed, because Org pri :action #'helm-org-goto-marker)))) #+END_SRC +** DONE [#A] Views: Multiple sorters are not preserved :bug: +:PROPERTIES: +:milestone: 0.5 +:url: https://github.com/alphapapa/org-ql/issues/136 +:END: + ** DONE [#A] Make dynamic blocks warn about sexp queries :PROPERTIES: :milestone: 0.5 From e2dbeb462098bc70cae116a1a5ba78e20575c870 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 18 Nov 2020 04:31:15 -0600 Subject: [PATCH 247/560] Notes: Move to meta/notes branch --- .gitignore | 2 + NOTES | 1 + notes.org | 4252 ---------------------------------------------------- 3 files changed, 3 insertions(+), 4252 deletions(-) create mode 100644 NOTES delete mode 100644 notes.org diff --git a/.gitignore b/.gitignore index fa4f2fc..9355658 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ /scratch.org /scratch/ /worktrees/ +/worktree/ +/NOTES.org diff --git a/NOTES b/NOTES new file mode 100644 index 0000000..b869aeb --- /dev/null +++ b/NOTES @@ -0,0 +1 @@ +Note: Notes are kept in the file "NOTES.org" in the "meta/notes" branch. diff --git a/notes.org b/notes.org deleted file mode 100644 index 95dc303..0000000 --- a/notes.org +++ /dev/null @@ -1,4252 +0,0 @@ -#+PROPERTY: LOGGING nil -#+TODO: TODO MAYBE NEXT PROJECT UNDERWAY WAITING | DONE(d) CANCELED - -* [#A] Contents -:PROPERTIES: -:TOC: :include siblings :depth 1 :ignore this :force depth -:END: -:CONTENTS: -- [[#overview][Overview]] -- [[#tasks][Tasks]] -- [[#checklists][Checklists]] -- [[#examples--testing][Examples / testing]] -- [[#in-the-wild][In the wild]] -- [[#profiling][Profiling]] -- [[#references][References]] -- [[#testing][Testing]] -:END: - -* [#A] Overview - -** Bugs ([[org-ql-search:todo%253A%2520tags%253Abug?super-groups=%2528%2528%253Aauto-property%2520%2522Milestone%2522%2529%2529&sort=%2528todo%2529&title=%2522Bugs%2522][view]]) - -#+BEGIN: org-ql :query "todo: tags:bug" :columns ((priority "P") ((property "milestone") "M") (todo "Keyword") heading) :sort (priority todo date) :ts-format "%Y-%m-%d %H:%M" -| P | M | Keyword | Heading | -|---+-----+---------+------------------------------------------------| -| A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -#+END: - -** Underway ([[org-ql-search:todo%253AUNDERWAY?sort=%2528priority%2529&title=%2522Underway%2522][view]]) - -#+BEGIN: org-ql :query "todo:UNDERWAY" :columns (((property "milestone") "M") (priority "P") (todo "Keyword") heading) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" -| M | P | Keyword | Heading | -|---+---+----------+--------------------------------------------------------------------| -| | B | UNDERWAY | [["Node" caching]["Node" caching]] | -| | | UNDERWAY | [[Benchmarking tags searches without and with new group-tags support][Benchmarking tags searches without and with new group-tags support]] | -#+END: - -** To-do ([[org-ql-search:todo:?super-groups=((:todo%20"NEXT")%20(:todo%20"PROJECT")%20(:auto-priority))&sort=(todo)][view]]) - -#+BEGIN: org-ql :query "todo: priority:A" :columns ((priority "P") ((property "milestone") "M") todo heading) :sort (priority date) :take 7 -| P | M | Todo | Heading | -|---+-----+---------+--------------------------------------------------------------| -| A | 0.5 | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| A | 0.5 | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| A | 0.5 | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| A | 0.5 | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | -| A | | PROJECT | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | -#+END: - -** Stuck projects ([[org-ql-search:%2528and%2520%2528todo%2520%2522PROJECT%2522%2529%2520%2528not%2520%2528descendants%2520%2528todo%2520%2522NEXT%2522%2529%2529%2529%2529?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528priority%2529&title=%2522Stuck%2520Projects%2522][view]]) - -#+BEGIN: org-ql :query (and (todo "PROJECT") (not (descendants (todo "NEXT")))) :columns (((property "milestone") "M") (priority "P") heading) :sort (priority date) :take 7 -| M | P | Heading | -|-----+---+-------------------------------------------------------| -| 0.5 | A | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| 0.5 | A | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| | A | [[Org%20link%20types%20%5B2/3%5D][Org link types {2/3}]] | -| | B | [[Move this notes file into an orphan =meta/notes= branch][Move this notes file into an orphan =meta/notes= branch]] | -| | B | [[Outline path predicate][Outline path predicate]] | -| 0.6 | B | [[Group tag support][Group tag support]] | -#+END: - -** Milestones ([[org-ql-search:todo%253A?super-groups=%2528%2528%253Aauto-property%2520%2522milestone%2522%2529%2529&sort=%2528todo%2529&title=%2522Milestones%2522][view]]) - -#+BEGIN: org-ql :query "todo: property:milestone" :columns (((property "milestone") "M") (priority "P") todo heading) :sort (priority date) :take 7 -| M | P | Todo | Heading | -|--------+---+---------+--------------------------------------------------------------| -| 0.5 | A | PROJECT | [[Compatibility with Org 9.4 custom link changes][Compatibility with Org 9.4 custom link changes]] | -| 0.5 | A | PROJECT | [[Convert simple sexp queries to non-sexp][Convert simple sexp queries to non-sexp]] | -| 0.5 | A | PROJECT | [[Checking links for unsafe parameters][Checking links for unsafe parameters]] | -| 0.5 | A | TODO | [[Tag org-super-agenda 1.2 and bump required version in org-ql][Tag org-super-agenda 1.2 and bump required version in org-ql]] | -| 0.6 | B | PROJECT | [[Group tag support][Group tag support]] | -| 0.6 | B | PROJECT | [[Save view to dynamic block][Save view to dynamic block]] | -| future | C | MAYBE | [[Alternative parsing libraries][Alternative parsing libraries]] | -#+END: - -* [#A] Tasks -:PROPERTIES: -:TOC: :include descendants :depth 1 -:END: -:CONTENTS: -- [[#add-auto-keyword-to-planning-predicate][Add :auto keyword to (planning) predicate]] -- [[#change-deadlines-auto-argument-to-auto-andor-auto-t][Change (deadline)'s auto argument to :auto and/or :auto t]] -- [[#outline-path-in-buffers-files-arg][Outline path in buffers-files arg]] -- [[#add-more-sorters][Add more sorters?]] -- [[#default-sort][Default sort]] -- [[#partial-match-for-property-queries][Partial match for property queries]] -- [[#org-agenda-skip-function][org-agenda-skip-function]] -- [[#update-commentary][Update commentary]] -- [[#org-ql-block-let-org-agenda-format-its-output][org-ql-block: Let org-agenda format its output]] -- [[#omnifocus-like-screencasts][OmniFocus-like screencasts]] -- [[#overlay-based-caching-inspired-by-org-num-mode][Overlay-based caching inspired by org-num-mode]] -- [[#alternative-parsing-libraries][Alternative parsing libraries]] -- [[#fancier-searching-for-inherited-tags][Fancier searching for inherited tags]] -- [[#compatibility-with-org-94-custom-link-changes][Compatibility with Org 9.4 custom link changes]] -- [[#convert-simple-sexp-queries-to-non-sexp][Convert simple sexp queries to non-sexp]] -- [[#checking-links-for-unsafe-parameters][Checking links for unsafe parameters]] -- [[#move-this-notes-file-into-an-orphan-metanotes-branch][Move this notes file into an orphan meta/notes branch]] -- [[#outline-path-predicate][Outline path predicate]] -- [[#tools-for-saving-queries-and-accessing-them-34][Tools for saving queries and accessing them {3/4}]] -- [[#group-tag-support][Group tag support]] -- [[#document-the-sorting-functions][Document the sorting functions]] -- [[#recursive-queries][Recursive queries]] -- [[#timeline-view][Timeline view]] -- [[#implement-view-with-tabulated-list-mode-or-magit-section][Implement view with tabulated-list-mode or magit-section]] -- [[#dynamic-blocks][Dynamic blocks]] -- [[#new-transient-transient-lisp-variable-class][New Transient transient-lisp-variable class]] -- [[#normalize-queries][Normalize queries]] -- [[#update-view-screenshots][Update view screenshots]] -- [[#test-caching][Test caching]] -- [[#node-caching]["Node" caching]] -- [[#views-multiple-sorters-are-not-preserved][Views: Multiple sorters are not preserved]] -- [[#make-dynamic-blocks-warn-about-sexp-queries][Make dynamic blocks warn about sexp queries]] -- [[#add-emacs-271-to-testyml][Add Emacs 27.1 to test.yml]] -- [[#fix-org-ql-view--link-open-on-org-93][Fix org-ql-view--link-open on Org 9.3+]] -- [[#fix-query-sexp-to-string-functions-handling-of-eg-descendants][Fix query-sexp-to-string function's handling of, e.g. descendants]] -- [[#helm-command][Helm command]] -- [[#quickly-change-sortinggrouping-in-search-views][Quickly change sorting/grouping in search views]] -- [[#byte-compile-lambdas][Byte-compile lambdas]] -- [[#documentfigure-out-tag-inheritance][Document/figure out tag inheritance]] -- [[#dual-matching-with-regexp-and-predicates][Dual matching with regexp and predicates]] -- [[#operate-on-list-of-heading-positions][Operate on list of heading positions]] -- [[#use-macros-for-date][Use macros for date]] -:END: - -** TODO [#B] Add ~:auto~ keyword to ~(planning)~ predicate - -It should act like ~(or (deadline auto) (scheduled :to today))~. - -** TODO [#B] Change ~(deadline)~'s ~auto~ argument to ~:auto~ and/or ~:auto t~ - -For consistency, because plain ~auto~ looks like a variable, and even though it's in a quoted form, it could be confusing. - - -** TODO [#B] Outline path in buffers-files arg -:PROPERTIES: -:ID: 6935361a-9e1d-48ec-8d17-876a90b90f50 -:END: - -e.g. - -#+BEGIN_SRC elisp - (org-ql (olp "~/org/inbox.org" "Emacs" "Ideas") - (todo "NEXT")) -#+END_SRC - -Also, should support an ~id~ one. - -** TODO [#B] Add more sorters? - -+ [ ] =category= -+ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry - -** TODO [#B] Default sort - -Would probably be useful to have a default sort option. - -** TODO [#B] Partial match for property queries - -e.g. something like [[https://200ok.ch/posts/2020-02-09_creating_org_mode_sparse_trees_in_emacs_and_organice.html][Organice has now]]. - -[2020-02-13 Thu 00:42] Something is needed to help search property values by partial matches. For example: - -#+BEGIN_SRC org - ,* [[https://github.com/fniessen/org-html-themes][org-html-themes: Framework including two themes, Bigblow and ReadTheOrg]] - :PROPERTIES: - :author: Fabrice Niessen - :END: - -#+END_SRC - -Searching that with a query like =property:author=Fabrice= returns nothing; the full value must be used, like ~property:author="Fabrice Niessen"~. It should be possible to do something like ~property:author=~Fabrice~ to search for partial matches. - -** TODO [#C] ~org-agenda-skip-function~ - -As discussed [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewi1q36/][here]], this is a cool feature that allows further integration into existing custom agenda commands. Example: - -#+BEGIN_SRC elisp - ;;; lima-0ac22.el --- -*- lexical-binding: t; -*- - - (defun org-ql-skip-function (query) - "Return a function for `org-agenda-skip-function' for QUERY. - Compared to using QUERY in `org-ql', this effectively turns QUERY - into (not QUERY)." - (let* ((predicate (org-ql--query-predicate '(regexp "ryo-modal")))) - (lambda () - ;; This duplicates the functionality of `org-ql--select'. - (let (orig-fns) - (--each org-ql-predicates - ;; Save original function mappings. - (let ((name (plist-get it :name))) - (push (list :name name :fn (symbol-function name)) orig-fns))) - (unwind-protect - (progn - (--each org-ql-predicates - ;; Set predicate functions. - (fset (plist-get it :name) (plist-get it :fn))) - ;; Run query. - ;; FIXME: "If this function returns nil, the current match should not be skipped. - ;; Otherwise, the function must return a position from where the search - ;; should be continued." - (funcall predicate)) - (--each orig-fns - ;; Restore original function mappings. - (fset (plist-get it :name) (plist-get it :fn)))))))) - - (let ((org-agenda-custom-commands - '(("z" "Z" - ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY")) - ((org-agenda-skip-function (org-ql-skip-function '(regexp "ryo-modal"))))) - ((org-agenda-files ("~/org/inbox.org")))))) - (org-agenda nil "z")) -#+END_SRC - -I should benchmark it to see how much difference it makes, because all those ~fset~ calls on each heading isn't free. But if a macro were used to rewrite the built-in predicates to their full versions, all of that could be avoided... - -** TODO [#C] Update commentary - -** MAYBE org-ql-block: Let org-agenda format its output - -[2020-11-16 Mon 22:12] As suggested by Kevin J. Foley. See [[https://github.com/alphapapa/org-ql/pull/113#issuecomment-728674220][#113]]. It might actually be simple to do and might work very well. - -** MAYBE OmniFocus-like screencasts - -[2020-11-18 Wed 03:03] Looking at OmniFocus's web site now, their short videos showing features demonstrate a lot of features that exist in org-ql already. After implementing section-based views, it would be cool to make some short demos showing similar features. - -** MAYBE [#C] Overlay-based caching inspired by org-num-mode - -[2019-12-30 Mon 22:42] Newer versions of Org have =org-num-mode=, which uses =font-lock= and =after-change-functions= to update overlays in the buffer with outline numbering. Maybe a similar approach could be used to cache arbitrary values for headings in a buffer without having to discard the whole buffer's cache when the buffer changes. - -[2020-11-09 Mon 01:51] I feel like that's probably unlikely to work well. I imagine it would require storing the query at every heading, which would be very wasteful. As well, adding more overlays to an Org buffer is probably not a good idea, because there are already enough of those. - -However, there might still be a useful idea here somewhere... - -** MAYBE [#C] Alternative parsing libraries -:PROPERTIES: -:milestone: future -:END: - -+ e.g. Bovine and Wisent come with Emacs, which would allow us to drop the =peg= dependency (which doesn't use lexical binding). -+ [[https://github.com/cute-jumper/parsec.el][parsec]] is third-party, but looks powerful - -** MAYBE [#C] Fancier searching for inherited tags - -When tag inheritance is enabled, and the given tags aren't file-level tags, we could search directly to headings containing the matching tags, and then only do per-heading matching on the subtrees. Sometimes that would be much faster. However, that might make the logic special-cased and complicated. Might need a redesign of the whole matching/predicate system to do cleanly. - -** PROJECT [#A] Compatibility with Org 9.4 custom link changes :bug: -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-13 Fri 22:36] From [[https://www.orgmode.org/Changes.html][the changelog]]: - -#+BEGIN_QUOTE -Calling conventions changes when opening or exporting custom links - -This changes affects export back-ends, and libraries providing new link types. - -Function used in :follow link parameter is required to accept a second argument. Likewise, function used in :export parameter needs to accept a fourth argument. See org-link-set-parameters for details. - -Eventually, the function org-export-custom-protocol-maybe is now called with a fourth argument. Even though the 3-arguments definition is still supported, at least for now, we encourage back-end developers to switch to the new signature. -#+END_QUOTE - -Unfortunately it does not say what the new, required second argument is. - - -** PROJECT [#A] Convert simple sexp queries to non-sexp -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-11 Wed 00:28] This will be very helpful for storing links. Surely simple ones won't be too hard... - -#+BEGIN_SRC elisp - (defun org-ql--query-sexp-to-plain (query) - "Return a plain query string for sexp QUERY. - If QUERY can't be converted to a plain one, return nil." - ;; This started out pretty simple...but at least it's not just one long function, right? - (cl-labels ((complex-p (query) - (or (contains-p 'or query))) - (contains-p (symbol list) - (cl-loop for element in list - thereis (or (eq symbol element) - (and (listp element) - (contains-p symbol element))))) - (format-args - (args) (let (non-paired paired next-keyword) - (cl-loop for arg in args - do (cond (next-keyword (push (cons next-keyword arg) paired) - (setf next-keyword nil)) - ((keywordp arg) (setf next-keyword (substring (symbol-name arg) 1))) - (t (push arg non-paired)))) - (string-join (append (mapcar #'format-atom non-paired) - (nreverse (--map (format "%s=%s" (car it) (cdr it)) - paired))) - ","))) - (format-atom - (atom) (cl-typecase atom - (string (if (string-match (rx space) atom) - (format "%S" atom) - (format "%s" atom))) - (t (format "%s" atom)))) - (format-form - (form) (pcase form - (`(not . (,rest)) (concat "!" (format-form rest))) - (`(priority . ,_) (format-priority form)) - ;; FIXME: Convert (src) queries to non-sexp form...someday... - (`(src . ,_) (user-error "Converting (src ...) queries to non-sexp form is not implemented")) - (_ (pcase-let* ((`(,pred . ,args) form) - (args-string (pcase args - ('() "") - ((guard (= 1 (length args))) (format "%s" (car args))) - (_ (format-args args))))) - (format "%s:%s" pred args-string))))) - (format-and - (form) (pcase-let* ((`(and . ,rest) form)) - (string-join (mapcar #'format-form rest) " "))) - (format-priority - (form) (pcase-let* ((`(priority . ,rest) form) - (args (pcase rest - (`(,(and comparator (or < <= > >= =)) ,letter) - (priority-letters comparator letter)) - (_ rest)))) - (concat "priority:" (string-join args ",")))) - (priority-letters - (comparator letter) (let* ((char (string-to-char (upcase (symbol-name letter)))) - (numeric-priorities '(?A ?B ?C)) - ;; NOTE: The comparator inversion is intentional. - (others (pcase comparator - ('< (--select (> it char) numeric-priorities)) - ('<= (--select (>= it char) numeric-priorities)) - ('> (--select (< it char) numeric-priorities)) - ('>= (--select (<= it char) numeric-priorities)) - ('= (--select (= it char) numeric-priorities))))) - (mapcar #'char-to-string others)))) - (unless (complex-p query) - (pcase query - (`(and . ,_) (format-and query)) - (_ (format-form query)))))) - - (--map (cons it (org-ql--query-sexp-to-plain it)) - '((priority >= B) - (priority > B) - (priority < B) - (priority < A) - (priority = A) - (todo) - (todo "TODO") - (todo "TODO" "NEXT") - (ts :from -1 :to 1) - (ts :on today) - (ts-active :from "2017-01-01" :to "2018-01-01") - (heading "quoted phrase" "word") - (and (tags "book" "books") (priority "A")) - (and (tags "space") (not (regexp "moon"))) - (src :lang "elisp" :regexps ("defun"))) - - - ) -#+END_SRC - -[2020-11-11 Wed 01:45] Seems to work well. Now to integrate that into link-saving... - -[2020-11-11 Wed 02:41] Seems to work. Will [[https://github.com/alphapapa/org-ql/issues/147#issuecomment-725287074][wait for feedback]] before merging. - -[2020-11-11 Wed 19:13] Seems to be working properly. One more thing to do though, I think: - -*** TODO [#B] Use string queries in view headers when possible - -Maybe make it an option to automatically convert them when possible, because if a user wanted to add complexity to a string query, he'd have to rewrite it as a sexp. - -** PROJECT [#A] Checking links for unsafe parameters -:PROPERTIES: -:ID: ba70e375-eddb-40df-8892-fb418c1f70d1 -:milestone: 0.5 -:END: -:LOGBOOK: -- State "PROJECT" from "UNDERWAY" [2020-11-12 Thu 00:26] -- State "UNDERWAY" from [2020-11-11 Wed 23:09] -:END: - -Theoretically one could put a sexp-based query into a link that would run arbitrary code to do something evil. Like: - -[[org-ql-search:(message "AHA")]] - -That's very unlikely to be abused, but it would be good to protect against it. Two possibilities: - -1. For sexp-based queries in links and dynamic blocks, prompt for confirmation before running. -2. Use a special variable to control whether lambdas and arbitrary sexps are allowed in queries, and disable it for links and dynamic blocks. (That might be difficult to do, since they could be buried in an ~and~ or something. A whitelist approach might be needed.) - -*** TODO [#A] Tag org-super-agenda 1.2 and bump required version in org-ql -:PROPERTIES: -:milestone: 0.5 -:END: - -That /should/ force the version of org-super-agenda with the fix to be installed when org-ql is upgraded. - -*** DONE Add automated tests -:LOGBOOK: -- State "UNDERWAY" from "TODO" [2020-11-12 Thu 00:24] -- State "TODO" from "MAYBE" [2020-11-11 Wed 23:16] -- State "MAYBE" from [2020-11-11 Wed 23:15] -:END: - -Maybe impractical, but maybe we could at least test that potentially unsafe ones signal errors. - -[2020-11-12 Thu 00:24] Works better than I expected. All the tests seem to correctly pass, signaling the correct errors for the correct reasons--except for the tests specific to org-super-agenda. For that, I'm currently waiting for MELPA to build the version of org-super-agenda that has the fix applied, so I can install that into the test sandbox, and then those two tests should pass also. - -*** DONE Enumerate and test parameters and potentially unsafe types -CLOSED: [2020-11-11 Wed 23:26] -:LOGBOOK: -- State "DONE" from "UNDERWAY" [2020-11-11 Wed 23:26] -- State "UNDERWAY" from [2020-11-11 Wed 23:15] -:END: - -#+CAPTION: Template for making testable links -#+BEGIN_SRC org -[[org-ql-search:todo:?]] -#+END_SRC - -#+CAPTION: Expression to insert encoded values into template (after the =?=) -#+BEGIN_SRC elisp - (insert (url-hexify-string (concat "buffers-files=" (prin1-to-string '((lambda () (message "AHA"))))))) -#+END_SRC - -+ [X] Buffers-Files: Expanded by =org-ql-view--expand-buffers-files=: - - [X] Quoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?buffers-files%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Quoted lambda in list (safe): [[org-ql-search:todo:?buffers-files%3D%28%28quote%20%28lambda%20nil%20%28message%20%22AHA%22%29%29%29%29]] - - [X] Unquoted lambda in list: (safe) [[org-ql-search:todo:?buffers-files%3D%28%28lambda%20nil%20%28message%20%22AHA%22%29%29%29]] -+ [X] Groups - - [X] Quoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda (safe): [[org-ql-search:todo:?super-groups%3D%28lambda%20nil%20%28message%20%22AHA%22%29%29]] - - [X] Quoted expression (safe): [[org-ql-search:todo:?super-groups%3D%28message%20%22AHA%22%29]] - - [X] Unquoted expression (safe): [[org-ql-search:todo:?super-groups%3D%22AHA%22]] - - [X] ~:pred~ selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Apred%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] - - [X] =:auto-map= selector (UNSAFE, but caught with new org-super-agenda variable): [[org-ql-search:todo:?super-groups%3D%28%28%3Aauto-map%20%28lambda%20%28_%29%20%28message%20%22AHA%22%29%29%29%29]] -+ [X] Title - - [X] Quoted lambda (produces the same encoded value as unquoted lambda): (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Unquoted lambda: (safe) [[org-ql-search:todo:?title%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Expression: (safe) [[org-ql-search:todo:?title%3D%28message%20%22AHA%22%29]] -+ [X] Sort - - [X] Bare, quoted lambda: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Bare, unquoted lambda: (UNSAFE, but caught now): [[org-ql-search:todo:?sort%3D%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29]] - - [X] Quoted lambda in list: (maybe unsafe, but caught now): [[org-ql-search:todo:?sort%3D%28%28quote%20%28lambda%20%28_%20_%29%20%28message%20%22AHA%22%29%29%29%29]] - - [X] Unquoted lambda in a list: (UNSAFE, but caught now): [[org-ql-search:todo:?sort=((lambda%20nil%20(message%20"AHA")))]] - -For the query expression: - -1. String queries are parsed by the PEG parsing function (which I will probably rename soon), which should only allow known Org QL predicates, not arbitrary functions. For example: - - #+BEGIN_SRC elisp - (org-ql--plain-query "message:AHA") ;;=> (regexp "message:AHA") - (org-ql--plain-query '(message "AHA")) ;;=> (wrong-type-argument stringp (message "AHA")) - (org-ql--plain-query "(message \"AHA\"") ;;=> (and (regexp "(message") (regexp "AHA")) - #+END_SRC - -2. Sexp queries already prompt for confirmation, unless the user has set =org-ql-view-ask-unsafe-links= to nil. - -[2020-11-11 Wed 23:27] That's all the parameters and all the types that I can think to test. - - -** PROJECT [#B] Move this notes file into an orphan =meta/notes= branch - -[2020-11-12 Thu 03:17] Will probably have to merge or delete some WIP branches first, otherwise they'll probably get conflicts. - -** PROJECT [#B] Outline path predicate - -[2019-10-07 Mon 11:15] There are two potential types of matching on outline paths: matching on any part of the outline path, and matching a specific path. For example, with this file: - -#+BEGIN_SRC org - ,* Food - - ,** Fruits - - ,*** Blueberries - - ,*** Grapes - - ,** Vegetables - - ,*** Carrots - - ,*** Potatoes -#+END_SRC - -Matching could work like this: - -+ ~(outline "Food")~ :: Would return all nodes. -+ ~(outline "Fruits")~ :: Would return all fruits. - -Matching at a specific path would be something like: - -+ ~(outline-path "Food" "Fruits")~ :: Would return all fruits. But if there were another =Fruits= heading somewhere in the file, under a different outline path, it would not return its nodes. - -I'm not sure the second type of matching belongs in predicates, but rather in [[id:6935361a-9e1d-48ec-8d17-876a90b90f50][this]]. - -To implement this with good performance probably needs an outline-path cache. I can probably repurpose the tags caching, but maybe it should be generalized. - -[2019-10-07 Mon 13:09] This is basically done with =be2bf6df316b96b3ed56851b8ffe0e227796b621= and =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but not the specific-path matching. I left a =MAYBE= in the code about "anchored" path matching, which would accomplish that. - -** PROJECT Tools for saving queries and accessing them [3/4] - -+ Added example to =examples.org=. - -*** PROJECT [#A] Org link types [2/3] -:PROPERTIES: -:ID: 4db73c1c-a4ed-425e-9e38-8d334ed03e1e -:END: - -This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. - -**** TODO For saved queries - -**** DONE For searches - -[2020-11-08 Sun 22:59] Let's try a very simple implementation so I could write a link like this to search the current buffer: - -#+BEGIN_SRC org - [[org-ql-search:property:author="AUTHOR"]] -#+END_SRC - -[2020-11-08 Sun 23:22] Seems to work! - -#+BEGIN_SRC elisp :results silent - ;;;; Org link type - - ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. - - (org-link-set-parameters "org-ql-search" - :follow #'org-ql-search--link-open - :store #'org-ql-search--link-store) - - (defun org-ql-search--link-open (query) - "Open Org QL QUERY for current buffer." - (org-ql-search (current-buffer) query)) - - (defun org-ql-search--link-store () - "Store a link to current Org QL query." - ;; TODO: When we have an org-ql-view-mode, test it here instead of org-ql-view-query. - (when org-ql-view-query - (org-store-link-props :type "org-ql-search" - :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) - :description org-ql-view-title) - t)) -#+END_SRC - -Tested on these queries: - -#+BEGIN_SRC org - + [[org-ql-search:(property%20:author%20"Chris%20Wellons")][org-ql-search:(property :author "Chris Wellons")]] - + [[org-ql-search:(link%20"nullprogram")][org-ql-search:(link "nullprogram")]] - + [[org-ql-search:link:nullprogram]] -#+END_SRC - -[2020-11-10 Tue 00:35] I'd like to support other parameters to the search, like grouping and sorting, so: - -#+BEGIN_SRC elisp :results silent - ;;;; Org link type - - ;; This section adds a custom link type to Org. See info:org#Adding hyperlink types. - - (org-link-set-parameters "org-ql-search" - :follow #'org-ql-search--link-open - :store #'org-ql-search--link-store) - - (defun org-ql-search--link-open (query) - "Open Org QL QUERY for current buffer." - (require 'url-parse) - (pcase-let* ((`(,query . ,params) - (url-path-and-query (url-parse-make-urlobj "org-ql-search" nil nil nil nil - query))) - (params (url-parse-query-string params)) - ;; Hacky or elegant? - (_ (mapc (lambda (pair) - (cl-callf (lambda (it) - (intern (concat ":" it))) - (car pair)) - (cl-callf read (cdr pair))) - params)) - (params (cl-loop for (key . value) in params - append (list key value)))) - (apply #'org-ql-search (current-buffer) query params))) - - (defun org-ql-search--link-store () - "Store a link to current Org QL query." - (when org-ql-view-query - (org-store-link-props :type "org-ql-search" - :link (concat "org-ql-search:" (org-ql-view--format-query org-ql-view-query)) - :description org-ql-view-title) - t)) -#+END_SRC - -That seems to work, like: - -#+BEGIN_SRC org - [[org-ql-search:property:author="Chris%20Wellons"?super-groups=((:auto-outline-path%20t))]] -#+END_SRC - -[2020-11-10 Tue 01:34] Okay, this seems to take care of all parameters: - -#+BEGIN_SRC elisp - (defun org-ql-search--link-open (path) - "Open Org QL query for current buffer at PATH. - PATH should be the part of an \"org-ql-search:\" URL after the - protocol. See, e.g. `org-ql-search--link-store'." - (require 'url-parse) - (require 'url-util) - (pcase-let* ((`(,query . ,params) (url-path-and-query - (url-parse-make-urlobj "org-ql-search" nil nil nil nil - path))) - (query (url-unhex-string query)) - (params (when params - (url-parse-query-string params))) - ;; `url-parse-query-string' returns "improper" alists, which makes this awkward. - (sort (when (alist-get "sort" params nil nil #'string=) - (read (alist-get "sort" params nil nil #'string=)))) - (groups (when (alist-get "super-groups" params nil nil #'string=) - (read (alist-get "super-groups" params nil nil #'string=)))) - (title (when (alist-get "title" params nil nil #'string=) - (read (alist-get "title" params nil nil #'string=))))) - (org-ql-search (current-buffer) query - :sort sort - :super-groups groups - :title title))) - - (defun org-ql-search--link-store () - "Store a link to the current Org QL view. - Only views that search a single buffer may be linked to." - (require 'url-parse) - (require 'url-util) - (unless (or (bufferp org-ql-view-buffers-files) (= 1 (length org-ql-view-buffers-files))) - (user-error "Only views searching a single buffer may be linked")) - (when org-ql-view-query - (let* ((params (list (when org-ql-view-super-groups - (list "super-groups" (prin1-to-string org-ql-view-super-groups))) - (when org-ql-view-sort - (list "sort" (prin1-to-string org-ql-view-sort))) - (when org-ql-view-title - (list "title" (prin1-to-string org-ql-view-title))))) - (filename (concat (url-hexify-string (org-ql-view--format-query org-ql-view-query)) - "?" (url-build-query-string (delete nil params)))) - (url (url-recreate-url (url-parse-make-urlobj "org-ql-search" nil nil nil nil - filename)))) - (org-store-link-props - :type "org-ql-search" - :link url - :description (concat "org-ql-search: " org-ql-view-title))) - t)) -#+END_SRC - -**** DONE For all parameters - -*** DONE Bookmarks - -[2020-11-08 Sun 23:25] Already done in =e5b4cd106558790563af26a8e32ec9508f904855=. - -*** DONE Access saved query from saved query list - -*** DONE Save query from ql-agenda buffer - -** PROJECT [#B] Group tag support -:PROPERTIES: -:milestone: 0.6 -:END: - -*** UNDERWAY Benchmarking tags searches without and with new group-tags support - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 10 :ensure-equal t - :forms (("without group-tags support" - (org-ql-select (org-ql-search-directories-files) - '(tags "Emacs") - :action #'point)) - )) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------------+--------------------+---------------+----------+------------------| -| without group-tags support | slowest | 5.512271 | 0 | 0 | - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 10 :ensure-equal t - :forms (("with group-tags support" - (org-ql-select (org-ql-search-directories-files) - '(tags "Emacs") - :action #'point)) - )) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------------+--------------------+---------------+----------+------------------| -| with group-tags support | slowest | 5.154639 | 0 | 0 | - -[2020-11-09 Mon 17:43] I think I need to enhance the benchmarking macros to make this easier. But that might require copying much of =benchmark-run-compiled=, so let me try something else: This is messy, but it ought to be fair enough (the only difference being the minor change in =org-ql--tags-at=. - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 10 :ensure-equal t - :forms (("without group-tags support" - (progn - (setf org-ql-cache (make-hash-table :weakness 'key) - org-ql-tags-cache (make-hash-table :weakness 'key) - org-ql-node-value-cache (make-hash-table :weakness 'key)) - (defun org-ql--expand-tag-hierarchy (tags &optional excluded) - "Return TAGS along with their associated group tags. - This function recursively searches for groups that each given tag belongs to, - directly or indirectly, and includes the corresponding group tags to the result. - - TAGS should be a list of tags (i.e., strings). - If non-nil, EXCLUDED should be a list of group tags that will not be - automatically added to the results unless they are already in TAGS." - (let ((groups (org-tag-alist-to-groups org-current-tag-alist)) - (excluded (append tags excluded))) - (let (group-tags) - (dolist (tag tags) - (pcase-dolist (`(,group-tag . ,group-members) groups) - (when (and (not (member group-tag excluded)) - ;; Check if one of the members in the group matches tag. - ;; Notice that each member may be a plain string or - ;; a regexp pattern (enclosed between curly brackets). - (--some (if (string-match-p "^[{].+[}]$" it) - ;; If pattern (it) is a regexp, remove the brackets and - ;; make sure that it either matches the whole tag or not. - (string-match-p (concat "^" (substring it 1 -1) "$") tag) - ;; Check if member (it) is identical to tag. - (string= it tag)) - group-members)) - (push group-tag group-tags)))) - ;; If group tags not already included have been found, - ;; then recursively expand them as well. - ;; Notice that by passing (group-tags excluded) to the next call - ;; instead of ((append tags group-tags)) ensures that we do not - ;; unnecessarily loop over the elements of TAGS more than once. - (if group-tags - (append tags (org-ql--expand-tag-hierarchy group-tags excluded)) - tags)))) - (defun org-ql--tags-at (position) - "Return tags for POSITION in current buffer. - Returns cons (INHERITED-TAGS . LOCAL-TAGS)." - ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables - ;; bound in the else clause, so destructured variables that are non-nil, - ;; like found caches, are not available in the else clause. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) - (modified-tick (car buffer-cache)) - (tags-cache (cdr buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cached-result (gethash position tags-cache))) - ;; Found in cache: return them. - (pcase cached-result - ('org-ql-nil nil) - (_ cached-result)) - ;; Not found in cache: get tags and cache them. - (let* ((local-tags (or (when (looking-at org-ql-tag-line-re) - (split-string (match-string-no-properties 2) ":" t)) - 'org-ql-nil)) - (inherited-tags (or (when org-use-tag-inheritance - (save-excursion - (if (org-up-heading-safe) - ;; Return parent heading's tags. - (-let* (((inherited local) (org-ql--tags-at (point))) - (tags (when (or inherited local) - (cond ((and (listp inherited) - (listp local)) - (->> (append inherited local) - -non-nil -uniq)) - ((listp inherited) inherited) - ((listp local) local))))) - (cl-typecase org-use-tag-inheritance - (list (setf tags (-intersection tags org-use-tag-inheritance))) - (string (setf tags (--select (string-match org-use-tag-inheritance it) - tags)))) - (pcase org-tags-exclude-from-inheritance - ('nil tags) - (_ (-difference tags org-tags-exclude-from-inheritance)))) - ;; Top-level heading: use file tags. - org-file-tags))) - 'org-ql-nil)) - (all-tags (list inherited-tags local-tags))) - ;; Check caches again, because they may have been set now. - ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? - (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) - modified-tick (car buffer-cache) - tags-cache (cdr buffer-cache) - buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (unless (and buffer-cache buffer-unmodified-p) - ;; Buffer-local tags cache empty or invalid: make new one. - (setf tags-cache (make-hash-table)) - (puthash (current-buffer) - (cons (buffer-modified-tick) tags-cache) - org-ql-tags-cache)) - (puthash position all-tags tags-cache)))) - (org-ql-select (org-ql-search-directories-files) - '(tags "Emacs") - :action #'point))) - ("with group-tags support" - (progn - (setf org-ql-cache (make-hash-table :weakness 'key) - org-ql-tags-cache (make-hash-table :weakness 'key) - org-ql-node-value-cache (make-hash-table :weakness 'key)) - (defun org-ql--expand-tag-hierarchy (tags &optional excluded) - "Return TAGS along with their associated group tags. - This function recursively searches for groups that each given tag belongs to, - directly or indirectly, and includes the corresponding group tags to the result. - - TAGS should be a list of tags (i.e., strings). - If non-nil, EXCLUDED should be a list of group tags that will not be - automatically added to the results unless they are already in TAGS." - (let ((groups (org-tag-alist-to-groups org-current-tag-alist)) - (excluded (append tags excluded))) - (let (group-tags) - (dolist (tag tags) - (pcase-dolist (`(,group-tag . ,group-members) groups) - (when (and (not (member group-tag excluded)) - ;; Check if one of the members in the group matches tag. - ;; Notice that each member may be a plain string or - ;; a regexp pattern (enclosed between curly brackets). - (--some (if (string-match-p "^[{].+[}]$" it) - ;; If pattern (it) is a regexp, remove the brackets and - ;; make sure that it either matches the whole tag or not. - (string-match-p (concat "^" (substring it 1 -1) "$") tag) - ;; Check if member (it) is identical to tag. - (string= it tag)) - group-members)) - (push group-tag group-tags)))) - ;; If group tags not already included have been found, - ;; then recursively expand them as well. - ;; Notice that by passing (group-tags excluded) to the next call - ;; instead of ((append tags group-tags)) ensures that we do not - ;; unnecessarily loop over the elements of TAGS more than once. - (if group-tags - (append tags (org-ql--expand-tag-hierarchy group-tags excluded)) - tags)))) - (defun org-ql--tags-at (position) - "Return tags for POSITION in current buffer. - Returns cons (INHERITED-TAGS . LOCAL-TAGS)." - ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables - ;; bound in the else clause, so destructured variables that are non-nil, - ;; like found caches, are not available in the else clause. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) - (modified-tick (car buffer-cache)) - (tags-cache (cdr buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cached-result (gethash position tags-cache))) - ;; Found in cache: return them. - (pcase cached-result - ('org-ql-nil nil) - (_ cached-result)) - ;; Not found in cache: get tags and cache them. - (let* ((local-tags (or (when (looking-at org-ql-tag-line-re) - (split-string (match-string-no-properties 2) ":" t)) - 'org-ql-nil)) - (inherited-tags (or (when org-use-tag-inheritance - (save-excursion - (if (org-up-heading-safe) - ;; Return parent heading's tags. - (-let* (((inherited local) (org-ql--tags-at (point))) - (tags (when (or inherited local) - (cond ((and (listp inherited) - (listp local)) - (->> (append inherited local) - -non-nil -uniq)) - ((listp inherited) inherited) - ((listp local) local))))) - (cl-typecase org-use-tag-inheritance - (list (setf tags (-intersection tags org-use-tag-inheritance))) - (string (setf tags (--select (string-match org-use-tag-inheritance it) - tags)))) - (pcase org-tags-exclude-from-inheritance - ('nil tags) - (_ (-difference tags org-tags-exclude-from-inheritance)))) - ;; Top-level heading: use file tags. - org-file-tags))) - 'org-ql-nil)) - all-tags) - (when org-group-tags - (unless (eq local-tags 'org-ql-nil) - (setq local-tags (org-ql--expand-tag-hierarchy local-tags))) - (unless (eq inherited-tags 'org-ql-nil) - (setq inherited-tags (org-ql--expand-tag-hierarchy inherited-tags)))) - (setq all-tags (list inherited-tags local-tags)) - ;; Check caches again, because they may have been set now. - ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? - (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) - modified-tick (car buffer-cache) - tags-cache (cdr buffer-cache) - buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (unless (and buffer-cache buffer-unmodified-p) - ;; Buffer-local tags cache empty or invalid: make new one. - (setf tags-cache (make-hash-table)) - (puthash (current-buffer) - (cons (buffer-modified-tick) tags-cache) - org-ql-tags-cache)) - (puthash position all-tags tags-cache)))) - (org-ql-select (org-ql-search-directories-files) - '(tags "Emacs") - :action #'point))) - )) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------------+--------------------+---------------+----------+------------------| -| without group-tags support | 1.01 | 52.832562 | 4 | 1.989522 | -| with group-tags support | slowest | 53.425342 | 5 | 2.479128 | - -[2020-11-09 Mon 17:57] Well, the performance difference seems smaller than I expected. For single iterations, it ought to be unnoticeable. Although I'm still a bit skeptical about this benchmark: I feel like it ought to have more of an impact than that, but maybe I'm wrong--and that would be great! - -Next steps: - -+ [X] Post benchmark code on PR and ask Panagiotis to verify -+ [X] Also ask him to run benchmark actually using group tags (since I don't actually have any, even though the boolean is t) -+ [X] Discuss caching of group tag expansion. It seems like we ought to cache the expansions as well, because sibling headings (especially at level 1) ought to get their group tags re-expanded individually, even when we've already expanded them for another heading. -+ [X] Remove unused =result= variable - -** PROJECT [#B] Document the sorting functions - -Note that the built-in sorting only works on Org elements, which is the default ~:action~. So if a different action is used, sorting will not work. In that case, the action should be mapped across the Org element results from outside the ~org-ql~ form. - - -** PROJECT [#B] Recursive queries - -For lack of a better term. A way to query for certain headings, and then gather results of a different query at each result of the first query, displaying all results in a single view. - -This works pretty well. It needs polishing, and some refactoring so items can be indented completely (rather than leaving the keyword unindented, as it is now). - -#+BEGIN_SRC elisp - (cl-defun org-ql-agenda-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil - (org-ql-agenda--agenda nil nil - :entries))))) - - (cl-defun org-ql-select-recursive (buffers-or-files queries &key action narrow sort) - (cl-labels ((rec (queries element indent) - (org-with-point-at (org-element-property :org-marker element) - (when-let* ((results (progn - (org-narrow-to-subtree) - (org-ql-select (current-buffer) - (car queries) - :action 'element-with-markers - :narrow t - :sort sort)))) - ;; Indent entry for each level - (setf results (--map - (org-element-put-property it :raw-value - (concat (s-repeat (* 5 indent) " ") - (org-element-property :raw-value it))) - results)) - (cons it (if (cdr queries) - (--map (rec (cdr queries) it) - results) - results)))))) - (when-let* ((indent 0) - (results (org-ql-select buffers-or-files - (car queries) - :action 'element-with-markers - :narrow narrow - :sort sort))) - (->> (if (cdr queries) - (--map (rec (cdr queries) it (1+ indent)) - results) - results) - (-flatten-n (1- (length queries))) - -non-nil)))) -#+END_SRC - -** PROJECT [#B] Timeline view -:PROPERTIES: -:ID: 00573552-ffe9-4608-8904-7f6c73246b6d -:END: - -e.g. as mentioned by Samuel Wales at https://lists.gnu.org/archive/html/emacs-orgmode/2019-08/msg00330.html. Prototype code: - -#+BEGIN_SRC elisp - (cl-defun org-ql-timeline (buffers-files query) - (let ((results - (org-ql-select buffers-files - query :action - (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (timestamps - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (ts-parse-org (match-string 0)))) - (timestamp-strings - (->> timestamps - (-sort #'ts<) - (--map (concat " " (ts-format it)))))) - (s-join "\n" (cons heading-string timestamp-strings)))) - :sort '(date)))) - (org-ql-agenda--agenda nil nil :strings results))) - - (org-ql-timeline (org-agenda-files) - '(and "Emacs" (ts))) - - ;; More timeline-like version, organized by date rather than task. - - (cl-defun org-ql-timeline* (buffers-files query &key filter-ts) - (let* ((ts-ht (ht)) - (results (org-ql-select buffers-files - query - :action (lambda () - (let* ((heading-string - (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-agenda--format-element)) - (date-timestamps - ;; Each one set to 00:00:00. - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both - limit t) - collect (->> (match-string 0) - ts-parse-org - (ts-apply :hour 0 :minute 0 :second 0))))) - (setf date-timestamps (delete-dups date-timestamps)) - (when filter-ts - (setf date-timestamps (cl-remove-if-not filter-ts date-timestamps))) - (--each date-timestamps - (push heading-string (gethash it ts-ht))))))) - (tss-sorted (-sort #'ts< (ht-keys ts-ht))) - (strings (cl-loop for ts in tss-sorted - collect (concat "\n" - (propertize (ts-format "%Y-%m-%d" ts) - 'face 'org-agenda-structure)) - append (ht-get ts-ht ts)))) - (org-ql-agenda--agenda nil nil :strings strings))) - - (org-ql-timeline* (org-agenda-files) - '(ts :from -14) - :filter-ts `(lambda (ts) - (ts<= ,(ts-adjust 'day -14 (ts-now)) ts))) -#+END_SRC - -Another, more up-to-date implementation: - -#+BEGIN_SRC elisp - ;; NOTE: ts structs don't (sometimes? or always?) compare properly - ;; with default hash tables, e.g. this code: - - ;; (let* ((ts-a #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572670800.0)) - ;; (ts-b #s(ts nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 1572584400.0))) - ;; (list :equal (equal ts-a ts-b) - ;; :sxhash-equal (equal (sxhash ts-a) (sxhash ts-b)))) ;;=> (:equal nil :sxhash-equal t) - - ;; So we must use the "contents-hash" table as described in the Elisp manual. - (define-hash-table-test 'contents-hash 'equal 'sxhash-equal) - - (cl-defun org-ql-view-timeline (buffers-files &key from to on) - "FIXME: DOcstring" - (cl-flet ((parse-ts-arg - (arg type) - ;; Parse ARG as a string or TS struct and adjust it to the beginning - ;; or end of its day, depending on whether TYPE is `:begin' or `:end'. - (-let (((hour minute second) (cl-ecase type - (:begin '(0 0 0)) - (:end '(23 59 59))))) - (->> (cl-typecase arg - (string (ts-parse arg)) - (ts arg)) - (ts-apply :hour hour :minute minute :second second))))) - (let* ((ts-predicate `(lambda (ts) - ,(cond (on `(ts-in ,(parse-ts-arg on :begin) - ts - ,(parse-ts-arg on :end))) - ((and from to) `(ts-in ,(parse-ts-arg from :begin) - ts - ,(parse-ts-arg to :end))) - (from `(ts<= ,(parse-ts-arg from :begin) ts)) - (to `(ts<= ts ,(parse-ts-arg to :end))) - (t (user-error "Huh?"))))) - (query (cond (on `(ts :from ,(parse-ts-arg on :begin) - :to ,(parse-ts-arg on :end))) - (t (append (list 'ts) - (when from - `(:from ,(parse-ts-arg from :begin))) - (when to - `(:to ,(parse-ts-arg to :end))))))) - (date-ts-table (make-hash-table :test 'contents-hash)) - (_results (org-ql-select buffers-files query - :action (lambda () - (let* ((string (->> (org-element-headline-parser - (line-end-position)) - org-ql--add-markers - org-ql-view--format-element))) - (cl-loop with limit = (org-entry-end-position) - while (re-search-forward org-ts-regexp-both limit t) - for ts = (->> (match-string 0) ts-parse-org) - when (funcall ts-predicate ts) - do (cl-pushnew (cons ts (concat (ts-format " %H:%M" ts) - string)) - (gethash (ts-apply :hour 0 :minute 0 :second 0 ts) - date-ts-table) - :test #'equal)))))) - (date-tss-sorted (->> date-ts-table hash-table-keys (-sort #'ts<))) - (string (cl-loop for date-ts in date-tss-sorted - for date-string = (propertize (ts-format "%Y-%m-%d" date-ts) - 'face 'org-agenda-structure) - concat (concat "\n" date-string) - concat (cl-loop for (ts . entry) in (->> (gethash date-ts date-ts-table) - (-sort (-on #'ts< #'car))) - concat (concat "\n" entry))))) - (org-ql-view--display :buffer "Timeline" - :header "Timeline" - :string string)))) - - ;; Used like: - ;; (org-ql-view-timeline "~/org/main.org" :from "2019-11-01") -#+END_SRC - -[2019-09-26 Thu 21:28] Would probably make sense to implement this using the view-sections someday. - -** PROJECT [#B] Implement view with tabulated-list-mode or magit-section - -[2019-09-02 Mon 05:20] Especially with some of the new packages that make =tabulated-list-mode= easier to use, like =navigel=. However, it would probably break grouping, or require some kind of adapter or extension to do grouping, so I don't know if that would work. Something like =magit-section= would be more flexible, and could be recursively grouped, like in =magit-todos=. - -[2019-09-08 Sun 10:06] Came up with a prototype yesterday, in branch =wip/view-section=. Seems to work pretty well. - -One of the things in that branch is =org-ql-item=, which is a struct used to carry data for query results. It seems to work well. - -Another idea for it is to simply store the element from =org-element-headline-parser= in one of its slots, and populate all of the other slots lazily, like =ts=. It already does that for a couple of slots, but I think it makes sense to do it for all of them, to reduce the overhead of making the struct for every query result. - -*** MAYBE [#C] Experiment with =widget= -:PROPERTIES: -:milestone: future -:END: - -The code that powers the customization UI. Has collapsible and customizable widgets. Might be perfect. Might even enable editing items in the list, with functions to make the changes in the source buffers. - -*** Code idea - -Inserting items into a view could look something like this: - -#+BEGIN_SRC elisp - (org-ql-view--insert-items - :header (ts-format "%Y-%m-%d" (ts-now)) - :items (org-ql-query - :select #'org-ql-current-item - :from (org-agenda-files) - :where '(or (deadline auto) - (scheduled :on today) - (ts-active :on today))) - :group-by '(org-ql-item-priority - org-ql-item-todo)) -#+END_SRC - -Items would be structs, and the =group-by= argument would be a list of accessors, like how =magit-todos= works. Arbitrary functions could also be passed to =group-by=, as whatever value the function returns is used to group them. =org-ql-current-item= would be a function that turns the result of =org-element-headline-parser= into the struct. - -Not sure if it should automatically add the number of items to the header, or if that should be done manually. - -*** Prior art - -**** [[https://github.com/m2ym/direx-el][GitHub - m2ym/direx-el: Directory Explorer for GNU Emacs]] - -Appears to be another implementation of magit-section-like expandable sections. Not sure which came first. Its code seems like it may be helpful. - -**** magit-section - -** PROJECT Dynamic blocks - -*** PROJECT [#B] Save view to dynamic block -:PROPERTIES: -:milestone: 0.6 -:END: - -[2020-11-10 Tue 04:31] A command would save users from having to write out the dynamic block manually. - -[2020-11-12 Thu 03:23] A command to do this would be very helpful. (Yes, I entered this idea twice. I should use my own systems better, apparently. But that's what this package is all about, right?) - -*** DONE [#A] Implement dynamic blocks - -+ *Tasks* - - [X] Merge code - - [X] Document the feature - -For example, [[https://egli.dev/posts/using-org-mode-for-meeting-minutes/][this blog article]] shows a way that Org's existing dynamic =columnview= blocks can be very useful. =org-ql= queries could be useful in them as well. - -[2020-11-09 Mon 22:00] I just realized that this is probably much easier than I realized. - -+ [[info:org#Dynamic%20blocks][info:org#Dynamic blocks]] - -#+BEGIN_SRC elisp - (cl-defun org-dblock-write:org-ql (params) - "FIXME: Docstring" - (pcase-let* (((map :query :columns :sort :ts-format) params) - (format-fns (list (cons 'heading (lambda (element) - (org-make-link-string (org-element-property :raw-value element) - (org-element-property :raw-value element)))) - (cons 'todo (lambda (element) - (or (org-element-property :todo-keyword element) - ""))) - (cons 'priority (lambda (element) - (--if-let (org-element-property :priority element) - (char-to-string it) - ""))) - (cons 'deadline (lambda (element) - (--if-let (org-element-property :deadline element) - (ts-format ts-format (ts-parse-org-element it )) - ""))) - (cons 'scheduled (lambda (element) - (--if-let (org-element-property :scheduled element) - (ts-format ts-format (ts-parse-org-element it )) - ""))))) - (elements (org-ql-query :from (current-buffer) - :where query - :select '(org-element-headline-parser (line-end-position)) - :order-by sort))) - (cl-labels ((format-element - (element) (string-join (cl-loop for column in columns - for fn = (alist-get column format-fns) - collect (funcall fn element)) - " | "))) - (insert "| " (string-join (--map (capitalize (symbol-name it)) columns) " | ") " |" "\n") - (insert "|- \n") - (dolist (element elements) - (insert "| " (format-element element) " |" "\n")) - (org-table-align)))) -#+END_SRC - -[2020-11-09 Mon 22:35] This works pretty well! For example: - -#+BEGIN_SRC org - ,#+BEGIN: org-ql :query (todo) :format (priority todo heading deadline scheduled) :sort (priority date) :ts-format "%Y-%m-%d %H:%M" - | Priority | Todo | Heading | Deadline | Scheduled | - |----------+-------+------------+------------------+------------------| - | A | TODAY | Heading 1 | 2020-11-11 00:00 | | - | B | TODO | Heading 2 | | 2020-11-09 00:00 | - - ,#+END: - - ,#+BEGIN: columnview :id global :hlines t :indent t - | ITEM | TODO | PRIORITY | TAGS | - |----------------+-------+----------+------| - | Test heading 1 | TODAY | B | | - |----------------+-------+----------+------| - | Heading 2 | TODO | B | | - ,#+END: - - ,* TODAY [#A] Heading 1 - DEADLINE: <2020-11-11 Wed> - - ,* TODO [#B] Heading 2 - SCHEDULED: <2020-11-09 Mon> - -#+END_SRC - -[2020-11-10 Tue 00:03] I think it's ready to merge now. - -*** DONE [#A] Org block to insert results of queries with links to entries -:PROPERTIES: -:ID: 422754bb-3a7c-4dbf-b303-4056d3cafb7e -:END: - -[2020-01-16 Thu 06:20] This idea just came to me when I was thinking about using the search-based paradigm vs. outline-based. This would allow both, e.g. some kind of =#+BEGIN_QUERY= block that would update when =C-c C-c= is pressed on it. - -[2020-11-13 Fri 22:57] I keep rediscovering ideas that I've had previously. This is now done as the dynamic block feature. I guess I should actually use these tools I've made. - -** PROJECT [#C] [[https://github.com/magit/transient/issues/76][New Transient transient-lisp-variable class]] :compatibility: - -[2020-10-19 Mon 00:23] Should try to use this instead of whatever bespoke code is currently used. - -** PROJECT [#C] Normalize queries - -[2019-07-16 Tue 11:49] This serves two purposes: - -1. Equivalent queries will return the same results from the cache. -2. The selectors that can be converted to the fastest preamble regexps will be sorted first, so the fastest preamble will be used. Although this may not always be straightforward. For example, in a file with only a few =TODO= items, the ~(todo "TODO")~ selector would convert to a preamble that would quickly search through the file. But if there were a thousand =TODO= items, it wouldn't be as much of a benefit, and a ~(regexp "something")~ selector's preamble might be much faster, depending on how many times =something= appears in the file. - -So the second purpose might actually be a drawback, because it would prevent users from optimizing their queries with knowledge of their data. Maybe there should be an option to not normalize queries, so advanced users can order their selectors manually. - -** PROJECT [#C] Update view screenshots - -e.g. doesn't currently show the =View= header. - -** PROJECT [#C] Test caching - -See notes on 1dce9467f25428b5289d3665cd840820969ed65a. It would be good to test the caching explicitly, at least for some queries, because if I were to completely break it again, in such a way that results were stored but retrieval always failed, the tests wouldn't catch it. - -** UNDERWAY [#B] "Node" caching - -[2019-09-05 Thu 12:30] At each node checked by a predicate, make a struct that stores attributes we can query for, as well as parent node position. This would let us speed up ancestor-based queries, like =(ancestor (todo "WAITING"))=. Ideally it would also serve as the tag hierarchy cache. - -It would probably be an all-encompassing system, because predicates would need to refer to the cached node when available. So maybe the struct should be like =ts-defstruct=, with lazy, caching accessors, which would move some of the predicates' code into the accessors. - -Maybe a good improvement to make later, after the project is more developed. - -[2019-10-07 Mon 13:08] This has basically been implemented in =be2bf6df316b96b3ed56851b8ffe0e227796b621=, but as functions and values rather than with structs. It remains to be seen how this works with =ancestor= queries, but I suspect it will help a lot. - -*** Struct PoC code - -This works okay (except the priority accessor needs to be fixed, because Org priorities are awkward to get). I'm guessing all the extra function calls would make it undesirable in cases of returning many results, but it's a flexible concept that makes sorting easy. - -#+BEGIN_SRC elisp - (ts-defstruct org-ql-node - file position marker - (level - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-outline-level))) - (heading - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - ;; TODO: Org 9.2+ adds 2 more args to `org-get-heading'. - (org-get-heading t t))) - (priority - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-get-priority ))) - (tags - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (->> (org-ql--tags-at (point)) - -flatten - (delq 'org-ql-nil)))) - (todo - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-get-todo-state))) - (outline-path - nil :accessor-init (org-with-point-at (org-ql-node-marker struct) - (org-split-string (org-format-outline-path (org-get-outline-path) - nil nil "") - "")))) - - (defcustom helm-org-ql-sort - '(org-ql-node-priority org-ql-node-todo) - "FIXME" - ) - - (cl-defun helm-org-ql (buffers-files &optional no-and) - "Display results in BUFFERS-FILES for an `org-ql' query using Helm. - Interactively, search the current buffer. - - NOTE: Atoms in the query are turned into strings where - appropriate, which makes it unnecessary to type quotation marks - around words that are intended to be searched for as indepenent - strings. - - Also, unless NO-AND is non-nil (interactively, with prefix), all - query tokens are wrapped in an implied (and) form. This is - because a query must be a sexp, so when typing multiple clauses, - either (and) or (or) would be required around them, and (and) is - typically more useful, because it narrows down results. - - For example, this raw input: - - Emacs git - - Is transformed into this query: - - (and \"Emacs\" \"git\") - - However, quoted strings remain quoted, so this input: - - \"something else\" (tags \"funny\") - - Is transformed into this query: - - (and \"something else\" (tags \"funny\"))" - (interactive (list (current-buffer) current-prefix-arg)) - (let ((helm-input-idle-delay helm-org-ql-input-idle-delay)) - (helm :sources - (helm-build-sync-source "helm-org-ql-agenda-files" - :candidates (lambda () - (let* ((query (helm-org-ql--input-to-query helm-pattern no-and)) - (window-width (window-width (helm-window)))) - (when query - (let ((results (org-ql-select buffers-files - query - :action '(make-org-ql-node :marker (point-marker))))) - (when helm-org-ql-sort - (dolist (sorter (reverse helm-org-ql-sort)) - (setf results (sort results sorter)))) - (cl-loop for it in-ref results - do (setf it (concat (buffer-name (org-ql-node-file it)) ":" - (or (org-ql-node-todo it) "") - (or (org-ql-node-priority it) "") - (org-ql-node-heading it) "\\" - (org-ql-node-outline-path it)))) - results)))) - :match #'identity - :fuzzy-match nil - :multimatch nil - :volatile t - :action #'helm-org-goto-marker)))) -#+END_SRC - -** DONE [#A] Views: Multiple sorters are not preserved :bug: -:PROPERTIES: -:milestone: 0.5 -:url: https://github.com/alphapapa/org-ql/issues/136 -:END: - -** DONE [#A] Make dynamic blocks warn about sexp queries -:PROPERTIES: -:milestone: 0.5 -:END: -:LOGBOOK: -CLOCK: [2020-11-16 Mon 22:56]--[2020-11-17 Tue 00:25] => 1:29 -:END: - -[2020-11-12 Thu 05:22] I guess to be super-extra careful, just in case someone had =org-update-all-dblocks= in the =before-save-hook= or something. - -[2020-11-17 Tue 00:25] It warns and the warning is tested. - -** DONE [#A] Add Emacs 27.1 to =test.yml= -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-16 Mon 05:22] Also releasing =makem.sh= 0.2 with this change. - -** DONE [#A] Fix =org-ql-view--link-open= on Org 9.3+ :compatibility:bug: -:PROPERTIES: -:milestone: 0.5 -:url: https://github.com/alphapapa/org-ql/issues/147 -:END: - -The version of Org in my personal that passes a URL-decoded string (i.e. as if run through =url-unhex-string=) as the argument to =org-ql-view--link-open=. But Org 9.3 in Emacs 27.1 passes a non-URL-decoded string, so =org-ql-view--link-open= needs to pass it through =url-unhex-string= itself. - -But I don't know which version of Org that changed in. I'm comparing the function =org-open-at-point=, but it's a 114-line function, and in neither version does it call =url-unhex-string=, so whatever code decodes the string must be elsewhere. - -I do recall something about links changing in Org 9.3 (or thereabouts), so that was probably part of it. Maybe I can find it in the release notes. I just need to know basically which version it happened in. - -I noticed because the CI tests on GitHub show the link-safety tests failing on the Emacs snapshot version. However, I think they're not currently vulnerable on that Org version, because the link parameters fail to be parsed correctly, so all the arguments to =org-ql-search= should end up being nil. - -[2020-11-14 Sat 20:41] I should probably do something like this in =org-ql-view--link-open=: - -#+BEGIN_SRC elisp - (when (version<= "9.3" (org-version)) - ;; Org 9.3+ makes a backward-incompatible change to link escaping. - ;; I don't think it would be a good idea to try to guess whether - ;; the string received by this function was made with or without - ;; that change, so we'll just test the current version of Org. - ;; Any links created with older Org versions and then opened with - ;; newer ones will have to be recreated. - (setf path (url-unhex-string path))) -#+END_SRC - -But, first, I should write tests for saving and opening links, so it can actually be tested on different versions automatically. - -[2020-11-16 Mon 05:12] Finally, all of the tests pass on my Org version and on 9.3. And I tested for all the combinations of link and bookmark saving/opening I could think of. I hope they work and are safe. - -*** DONE [#A] Write tests for storing/opening links -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-16 Mon 05:11] Took way longer than I expected. I hope it was worth it. - -*** DONE [#A] Check Org release notes for link changes - -[2020-11-13 Fri 22:44] From [[https://www.orgmode.org/Changes_old.html][the changelog]]: - -#+BEGIN_QUOTE -Change bracket link escaping syntax - -Org used to percent-encode sensitive characters in the URI part of the bracket links. - -Now, escaping mechanism uses the usual backslash character, according to the following rules, applied in order: - -- All consecutive \ characters at the end of the link must be escaped; -- Any ] character at the very end of the link must be escaped; -- All consecutive \ characters preceding ][ or ]] patterns must be escaped; -- Any ] character followed by either [ or ] must be escaped; -- Others ] and \ characters need not be escaped. - -When in doubt, use the function org-link-escape in order to turn a link string into its properly escaped form. - -The following function will help switching your links to the new syntax: - -(defun org-update-link-syntax (&optional no-query) - "Update syntax for links in current buffer. -Query before replacing a link, unless optional argument NO-QUERY -is non-nil." - (interactive "P") - (org-with-point-at 1 - (let ((case-fold-search t)) - (while (re-search-forward "\\[\\[[^]]*?%\\(?:2[05]\\|5[BD]\\)" nil t) - (let ((object (save-match-data (org-element-context)))) - (when (and (eq 'link (org-element-type object)) - (= (match-beginning 0) - (org-element-property :begin object))) - (goto-char (org-element-property :end object)) - (let* ((uri-start (+ 2 (match-beginning 0))) - (uri-end (save-excursion - (goto-char uri-start) - (re-search-forward "\\][][]" nil t) - (match-beginning 0))) - (uri (buffer-substring-no-properties uri-start uri-end))) - (when (or no-query - (y-or-n-p - (format "Possibly obsolete URI syntax: %S. Fix? " - uri))) - (setf (buffer-substring uri-start uri-end) - (org-link-escape (org-link-decode uri))))))))))) - -The old org-link-escape and org-link-unescape functions have been renamed into org-link-encode and org-link-decode. -#+END_QUOTE - -This is exactly the kind of breaking, backwards-incompatible change that I've said should mandate a major-version increment. It's not only a change in Org's code, and a change that affects third-party packages, but it's a change in the file format! - -Is it even possible to support both Org 9.3+ and earlier versions at the same time? - -This change doesn't even seem to make sense to me. Percent-encoding solves so many problems in a simple way: pass a string to the encoding function on the way in, and to the decoding function on the way out. Now, instead of a simple, standard way of encoding links, there's a list of Org-specific rules and Org-specific encoding/decoding functions. What is gained this way? - - -** DONE [#A] Fix query-sexp-to-string function's handling of, e.g. =descendants= :bug: -:PROPERTIES: -:milestone: 0.5 -:END: - -[2020-11-14 Sat 20:45] Fixed in =89ff02a1501b53b4e20cdc66a8fcaa37e7d15734=. - -** DONE [#A] Helm command - -In branch =wip/helm-org-ql=. Works really well, should add it and demonstrate it. - -*** DONE Add - -*** DONE Demonstrate - -*** DONE Parsing non-Lisp queries - -[2019-09-12 Thu 12:56] Lisp is so much easier to deal with, but some people don't like parentheses. So I'm trying to add a non-Lisp-style query syntax. It gets complicated. The =peg= library helps, but its documentation is sparse and incomplete. This seems to work fairly well for single-token queries, but I'm not sure if I can or should cram it all into one parser, or use separate ones for certain keywords. - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror)) - ((predicate . args) (nreverse parsed))) - (when predicate - (list :predicate predicate :args args :combinator combinator))) - ;;=> (:predicate "heading" :args ("spaced phrase" "another" t) :combinator and) -#+END_SRC - -I don't know where the =t= is coming from. - -The next step is to make it work with multi-token queries. It needs to handle all of the tokens in one parser so it can handle quoted phrases (if we split on spaces, it would split quoted phrases). But that makes getting the arguments out of it more difficult. Probably need to do something like this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (syntax-class whitespace)))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (+ (and (or quoted-arg unquoted-arg) (opt separator)))) - (quoted-arg "\"" unquoted-arg "\"") - (unquoted-arg (substring (+ (not (or separator "\"")) (any)))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) -#+END_SRC - -In which lists are pushed onto the stack and returned, rather than strings. But I don't understand yet exactly how to use the =var= forms to consume input from the "value stack"; I need to study the examples more. I'm also not sure if that will even work with a variable number of arguments. - -This seems to work, but we'll have to parse the args again in a separate step: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (substring (+ (and (or quoted-arg unquoted-arg) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args "check") (:predicate "heading" :args "\"spaced phrase\"+another")) -#+END_SRC - -Well, a bit of fiddling (lots of trial-and-error required) produced this: - -#+BEGIN_SRC elisp - (-let* ((input "todo:check|someday") - (input "tags:universe+space") - (input "heading:\"spaced phrase\"") - (input "") - (input "heading:\"spaced phrase\"+another") - (input "heading:\"spaced phrase\"+another todo:check") - combinator - (parsed (peg-parse-string ((query (+ (or (and predicate `(pred args -- (list :predicate pred :args args))) - (and plain-string `(s -- (list :predicate 'regexp :args s)))) - (opt (+ (syntax-class whitespace) (any))))) - (plain-string (substring (+ (not (syntax-class whitespace)) (any)))) - (predicate (substring keyword) ":" (opt args)) - (keyword (or "heading" "tags" "todo" "property")) - (args (list (+ (and (substring (or quoted-arg unquoted-arg)) (opt separator))))) - (quoted-arg "\"" (+ (not (or separator "\"")) (any)) "\"") - (unquoted-arg (+ (not (or separator "\"" (syntax-class whitespace))) (any))) - (separator (or (and "|" (action (setf combinator 'or))) - (and "+" (action (setf combinator 'and))) - (and ":" (action (setf combinator 'arg)))))) - input 'noerror))) - parsed) - ;;=> (t (:predicate "todo" :args ("check")) (:predicate "heading" :args ("\"spaced phrase\"" "another"))) -#+END_SRC - -That seems pretty usable! - -** DONE [#B] Quickly change sorting/grouping in search views - -With caching, the search doesn't need to be repeated, so resorting/regrouping can be very fast. - -** DONE Byte-compile lambdas -CLOSED: [2018-05-09 Wed 17:30] -:LOGBOOK: -- State "DONE" from [2018-05-09 Wed 17:30] -:END: - -=elfeed-search--update-list= byte-compiles lambdas returned by =elfeed-search-compile-filter=. Maybe I could do something like this too. - -If I can get this working, I should profile it to see what difference it makes. - -*** Profiling - -Going to try byte-compiling the predicate function: - -#+BEGIN_SRC elisp - (elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date :date '= (org-today)) - (date :deadline '<= (+ org-deadline-warning-days (org-today))) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| org-agenda-ng--agenda | 10 | 0.8370581039 | 0.0837058104 | -| org-agenda-finalize-entries | 10 | 0.652886608 | 0.0652886608 | -| org-super-agenda--filter-finalize-entries | 10 | 0.641794501 | 0.0641794501 | -| org-super-agenda--group-items | 10 | 0.636057006 | 0.0636057006 | -| org-super-agenda--group-dispatch | 130 | 0.631911849 | 0.0048608603 | -| org-super-agenda--group-tag | 50 | 0.592883869 | 0.0118576773 | -| list | 2720 | 0.5792795169 | 0.0002129704 | -| mapcar | 331 | 0.2333591920 | 0.0007050126 | -| org-agenda-ng--filter-buffer | 10 | 0.09247626 | 0.009247626 | -| org-agenda-ng--format-element | 150 | 0.0649320479 | 0.0004328803 | -| org-entry-get | 860 | 0.0408285349 | 4.747...e-05 | -| org-agenda-ng--date-p | 910 | 0.0385646249 | 4.237...e-05 | -| org-element-headline-parser | 150 | 0.0374417470 | 0.0002496116 | -| org-is-habit-p | 270 | 0.0290107389 | 0.0001074471 | -| org--property-local-values | 270 | 0.0268615979 | 9.948...e-05 | -| org-get-property-block | 270 | 0.0244613309 | 9.059...e-05 | -| org-get-tags-at | 150 | 0.017875864 | 0.0001191724 | -| org-super-agenda--group-habit | 10 | 0.015910656 | 0.0015910655 | -| mapc | 2540 | 0.0158616290 | 6.244...e-06 | -| org-agenda-ng--add-faces | 150 | 0.0143329670 | 9.555...e-05 | - - -Now the same thing without byte-compiling: - -#+BEGIN_SRC elisp - (elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date :date '= (org-today)) - (date :deadline '<= (+ org-deadline-warning-days (org-today))) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| org-agenda-ng--agenda | 10 | 0.846645537 | 0.0846645537 | -| org-agenda-finalize-entries | 10 | 0.662896805 | 0.0662896805 | -| sort | 40 | 0.591123256 | 0.0147780814 | -| org-entries-lessp | 400 | 0.5901201620 | 0.0014753004 | -| mapcar | 201 | 0.2318270599 | 0.0011533684 | -| org-agenda-ng--filter-buffer | 10 | 0.092519787 | 0.0092519787 | -| org-super-agenda--filter-finalize-entries | 10 | 0.0664278040 | 0.0066427804 | -| org-agenda-ng--format-element | 150 | 0.064658994 | 0.0004310599 | -| org-super-agenda--group-items | 10 | 0.0602504089 | 0.0060250408 | -| org-super-agenda--group-dispatch | 130 | 0.0561904470 | 0.0004322342 | -| org-entry-get | 860 | 0.0437458889 | 5.086...e-05 | -| org-agenda-ng--date-p | 910 | 0.0382623409 | 4.204...e-05 | -| org-element-headline-parser | 150 | 0.0374662920 | 0.0002497752 | -| org-is-habit-p | 270 | 0.0320861079 | 0.0001188374 | -| org--property-local-values | 270 | 0.0298690430 | 0.0001106260 | -| org-get-property-block | 270 | 0.0274716649 | 0.0001017469 | -| org-super-agenda--group-habit | 10 | 0.019117901 | 0.0019117901 | -| org-get-tags-at | 150 | 0.0178958930 | 0.0001193059 | -| mapc | 2470 | 0.0150361130 | 6.087...e-06 | -| org-agenda-ng--add-faces | 150 | 0.0143092169 | 9.539...e-05 | - -Virtually indistinguishable. Going to try moving the =byte-compile= call from the =org-agenda-ng= macro to other places... - -#+BEGIN_SRC elisp - (elp-profile 10 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date :date '= (org-today)) - (date :deadline '<= (+ org-deadline-warning-days (org-today))) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| org-agenda-ng--agenda | 10 | 0.8476316779 | 0.0847631678 | -| mapcar | 331 | 0.8159452220 | 0.0024650913 | -| org-agenda-ng--filter-buffer | 10 | 0.674217912 | 0.0674217912 | -| org-element-headline-parser | 150 | 0.6171195889 | 0.0041141305 | -| line-beginning-position | 620 | 0.5802579680 | 0.0009358999 | -| org-agenda-finalize-entries | 10 | 0.082065157 | 0.0082065157 | -| org-super-agenda--filter-finalize-entries | 10 | 0.0708772279 | 0.0070877227 | -| org-super-agenda--group-items | 10 | 0.065523103 | 0.0065523103 | -| org-agenda-ng--format-element | 150 | 0.0652783740 | 0.0004351891 | -| org-super-agenda--group-dispatch | 130 | 0.0614253589 | 0.0004725027 | -| org-entry-get | 860 | 0.0494023029 | 5.744...e-05 | -| org-agenda-ng--date-p | 910 | 0.0388435519 | 4.268...e-05 | -| org-is-habit-p | 270 | 0.0375687549 | 0.0001391435 | -| org--property-local-values | 270 | 0.0353892929 | 0.0001310714 | -| org-get-property-block | 270 | 0.0329700440 | 0.0001221112 | -| org-super-agenda--group-habit | 10 | 0.024468601 | 0.0024468601 | -| re-search-backward | 1500 | 0.0186344089 | 1.242...e-05 | -| org-get-tags-at | 150 | 0.0180038809 | 0.0001200258 | -| mapc | 2540 | 0.0156518099 | 6.162...e-06 | -| org-agenda-ng--add-faces | 150 | 0.0144141080 | 9.609...e-05 | - -Doesn't seem to make any difference. - -** DONE Document/figure out tag inheritance - -I think it should probably be enabled in most cases, to avoid missing results that users would expect to find, but it will reduce performance in some cases, so users should be able to turn it off when they don't need it. - -[2018-06-12 Tue 14:32] The docstring for ~org-map-entries~ says: - -#+BEGIN_QUOTE -If your function needs to retrieve the tags including inherited tags at the *current* entry, you can use the value of the variable ‘org-scanner-tags’ which will be much faster than getting the value with ‘org-get-tags-at’. If your function gets properties with ‘org-entry-properties’ at the *current* entry, bind ‘org-trust-scanner-tags’ to t around the call to ‘org-entry-properties’ to get the same speedup. Note that if your function moves around to retrieve tags and properties at a *different* entry, you cannot use these techniques. -#+END_QUOTE - -[2019-09-26 Thu 21:31] Handled with the tag caching recently implemented. - -** DONE [#B] Dual matching with regexp and predicates -:PROPERTIES: -:ID: 39972bb5-fdd0-4754-93ba-c85796a67ccf -:END: - -/Note: This is underway in the =preamble-re= branch./ - -Searching and matching could be sped up by constructing a regexp that searches directly to the next possible match, and then matching with predicate functions. - -For example, a search like: - -#+BEGIN_SRC elisp - (org-ql (org-agenda-files) - (and (regexp "lisp") - (scheduled < today))) -#+END_SRC - -Only entries that contain the word =lisp= can be matches, and searching each entry for that word is wasteful. Instead, we could search the buffer for the next occurrence of =lisp=, then check the scheduled date for that entry. - -This would require processing the predicate to pull out matchers that can be done as buffer-wide regexps, e.g. =regexp=, =heading-regexp=, =todo=, and possibly =tags=. Org has some regexp-building functions that might make this fairly easy, and then we could probably use ~rx~ to make an optimized version of the regexp. It would also require some refactoring to the searching that would go directly to regexp matches when possible, rather than checking every entry with the predicate. - -[2019-07-16 Tue 11:14] Made new branch =preamble-re-new= based on current =master=. Seems to work well. Here's some code for testing and comparing performance (~bench-multi-lets~ is from [[https://github.com/alphapapa/emacs-package-dev-handbook#bench-multi-lets][here]]). - -[2019-07-16 Tue 11:56] Going to merge to =master= as 0.2, so marking this as done, even though there's a bit more that can be done from here. - -*** Benchmark code - -#+BEGIN_SRC elisp - (cl-defmacro org-ql-preamble-bench (&key query (file "tests/data.org") (times 10)) - `(bench-multi-lets :times ,times :ensure-equal t - :lets (("preamble" ((org-ql-use-preamble t))) - ("no preamble" ((org-ql-use-preamble nil)))) - :forms ((,(prin1-to-string query) (org-ql-select,file - ',query - :action (lambda () (org-get-heading t t))))))) -#+END_SRC - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :query (regexp "Emacs") :times 100) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------------------+--------------------+---------------+----------+------------------| -| preamble: (regexp "Emacs") | 1.22 | 0.141767 | 0 | 0 | -| no preamble: (regexp "Emacs") | slowest | 0.172398 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :file "~/org/inbox.org" :query (regexp "Emacs") :times 5) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------------------+--------------------+---------------+----------+------------------| -| preamble: (regexp "Emacs") | 1.59 | 2.011043 | 0 | 0 | -| no preamble: (regexp "Emacs") | slowest | 3.206370 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :file "~/org/inbox.org" :query (and (regexp "Emacs") (todo)) :times 5) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (and (regexp "Emacs") (todo)) | 1.59 | 2.211503 | 0 | 0 | -| no preamble: (and (regexp "Emacs") (todo)) | slowest | 3.512741 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :file "~/org/inbox.org" :query (and (regexp "Emacs") (todo) (scheduled)) :times 5) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (and (regexp "Emacs") (todo) (scheduled)) | 1.69 | 2.042456 | 0 | 0 | -| no preamble: (and (regexp "Emacs") (todo) (scheduled)) | slowest | 3.453756 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :file "~/org/inbox.org" :query (todo "WAITING") :times 2) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------------------+--------------------+---------------+----------+------------------| -| preamble: (todo "WAITING") | 15.60 | 0.070684 | 0 | 0 | -| no preamble: (todo "WAITING") | slowest | 1.102722 | 0 | 0 | - -Wow, that's a huge improvement! - -** DONE Operate on list of heading positions -CLOSED: [2018-05-10 Thu 15:02] -:LOGBOOK: -- State "DONE" from [2018-05-10 Thu 15:02] -:END: - -[2017-12-31 Sun 17:54] I wonder if, instead of parsing the whole buffer with =org-element-parse-buffer=, we could simply work on a list of heading positions, e.g. a loop would search forward to the next heading position, then call whatever predicates it needed at the heading's position, using =save-excursion= around each function call. The predicates would need to be updated to get their data from the buffer, instead of using =org-element-property=, but that wouldn't be hard. - -[2018-05-10 Thu 15:01] I already changed to using buffer-parsing predicates instead of =org-element-parse-buffer=. - -** DONE Use macros for =date= -CLOSED: [2018-05-10 Thu 14:59] -:LOGBOOK: -- State "DONE" from [2018-05-10 Thu 14:59] -:END: - -If I made the =date= selector a macro, I could avoid the need to quote the comparator. - -Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc. - -* Checklists - -** Commit - -*** Fix - -+ [ ] Check repo for closing issue -+ [ ] Check this file for closing task -+ [ ] Lint -+ [ ] Test -+ [ ] Commit and push - -* Examples / testing -:PROPERTIES: -:TOC: :include descendants :depth 1 -:END: -:CONTENTS: -- [[#property-matching][Property matching]] -- [[#regexp-matching][Regexp matching]] -- [[#screenshot-code][Screenshot code]] -- [[#sorting][Sorting]] -:END: - -#+BEGIN_SRC elisp - (org-agenda-ng org-agenda-files - (and (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))) - ((group (tags "bills")) - (group (todo "SOMEDAY")))) - - (org-agenda-ng org-agenda-files - (and (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))) - - (org-agenda-ng "~/org/main.org" - (and (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))) - - (org-ql org-agenda-files - (and (todo "SOMEDAY") - (tags "Emacs"))) - (org-ql org-agenda-files - (and (todo "SOMEDAY") - (tags "Emacs") - (priority >= "B"))) - (org-ql "~/org/main.org" - (and (or (tags "Emacs") - (priority >= "B")) - (not (done)))) - (org-ql "~/org/main.org" - (and (or (tags "Emacs") - (priority >= "B")) - (done))) -#+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 - -** Regexp matching - -#+BEGIN_SRC elisp - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (regexp "over")) - - (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (regexp "over")) -#+END_SRC - -** Screenshot code - -#+BEGIN_SRC elisp - (org-super-agenda--test-with-org-today-date "2017-07-08 00:00" - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date = today) - (deadline <=) - (scheduled <= today)) - (not (done))))) -#+END_SRC - -** Sorting - -#+BEGIN_SRC elisp - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (regexp "over") - :sort (priority deadline scheduled)) - - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (regexp "over") - :sort (date)) - - (org-ql "~/src/emacs/org-super-agenda/test/test.org" - (todo) - :sort (todo)) -#+END_SRC - -* In the wild -:PROPERTIES: -:TOC: :include descendants :depth 1 -:END: -:CONTENTS: -- [[#alois-janicek][Alois Janicek]] -- [[#benson-chu][Benson Chu]] -:END: - -** [[https://github.com/AloisJanicek/.doom.d-2nd][Alois Janicek]] - -*** [[https://github.com/AloisJanicek/.doom.d-2nd/commit/41ed1080f6f90463fc1f1d7e47cef9864756867c][further tweaking org-ql views · AloisJanicek/.doom.d-2nd@41ed108 · GitHub]] - -#+BEGIN_SRC elisp :eval never -;; Hydras -(defhydra gtd-agenda (:color blue - :body-pre - (if (aj/has-heading-p +INBOX) - (org-ql-search `(,+INBOX) "*" - :sort '(date)) - (org-ql-search (org-agenda-files) - '(todo "NEXT") - :sort '(date priority todo) - :groups '((:auto-category t)))) - ) - "agenda" - ("a" (org-ql-agenda (org-agenda-files) - (and (or (ts-active :on today) - (deadline auto) - (scheduled :to today)) - (not (done)))) "agenda") - - ("t" (org-ql-search (org-agenda-files) - '(todo "TODO") - :sort '(date priority todo) - :groups '((:auto-category t))) "todo") - - ("n" (org-ql-search (org-agenda-files) - '(todo "NEXT") - :sort '(date priority todo) - :groups '((:auto-category t))) "next") - - ("h" (org-ql-search (org-agenda-files) - '(todo "HOLD") - :sort '(date priority todo) - :groups '((:auto-category t))) "hold") - - ("s" (org-ql-search (org-agenda-files) - '(tags "someday") - :sort '(date priority todo) - :groups '((:auto-category t))) "someday") - - ("r" (org-ql-search (org-agenda-files) - '(ts :from -7 :to today) - :sort '(date priority todo) - :groups '((:auto-ts t))) "recent") - - ("i" (org-ql-search `(,+INBOX) "*" - :sort '(date)) "inbox") - ) -#+END_SRC - -** [[https://github.com/pestctrl/emacs-config][Benson Chu]] - -*** [[https://github.com/pestctrl/emacs-config/commit/fa3068003373a0c93e23c728b5dbad2d7c11e2e1][Experimental agenda view with org-ql · pestctrl/emacs-config@fa30680 · GitHub]] - -#+BEGIN_SRC elisp :eval never - ("f" "fastdev?" - ((org-ql-block '(tags "refile") - ((org-agenda-overriding-header "Refile tasks"))) - (tags-todo ,(concat dev-tag "/!" (mapconcat #'identity my/active-projects-and-tasks "|")) - ((org-agenda-overriding-header "Stuck Projects") - (org-agenda-skip-function 'my/dev-show-stuck-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '((agenda category-keep))))) - (tags-todo ,(concat dev-tag "-short" "/!" (mapconcat #'identity my/active-projects-and-tasks "|")) - ((org-agenda-overriding-header "Active Projects") - (org-agenda-skip-function 'my/dev-show-active-projects) - (org-tags-match-list-sublevels 'indented) - (org-agenda-sorting-strategy - '((agenda category-keep))))) - (org-ql-block '(and (tags "dev") - (todo "WAIT")) - ((org-agenda-overriding-header "Waiting tasks"))) - (org-ql-block '(and (tags "dev") - (todo "NEXT")) - ((org-agenda-overriding-header "Things to do"))) - (agenda "" - ((org-agenda-skip-function 'my/agenda-custom-skip) - (org-agenda-span 'day) - (org-agenda-tag-filter-preset (quote (,dev-tag))) - (org-agenda-skip-deadline-if-done t) - (org-agenda-skip-scheduled-if-done t) - (org-super-agenda-groups '((:name "Overdue" :and (:deadline past :log nil)) - (:name "Upcoming" :deadline future) - (:name "Should do" :and (:scheduled past :log nil)) - (:name "Today" :time-grid t - :and (:not (:and (:not (:scheduled today) - :not (:deadline today))))))))))) -#+END_SRC - -* Profiling -:PROPERTIES: -:TOC: :include descendants :depth 1 -:END: - -:CONTENTS: -- [[#2019-08-29-thu-0624--benchmarking-org-ql-compared-to-re-search-forward-for-getting-headings-in-buffer][{2019-08-29 Thu 06:24} Benchmarking org-ql compared to re-search-forward for getting headings in buffer]] -- [[#caching-of-inherited-tags][Caching of inherited tags]] -- [[#intersecting-query-results][Intersecting query results]] -- [[#more-profiling][More profiling]] -- [[#preambles][Preambles]] -- [[#profiling-flet-across-all-agenda-files][Profiling flet across all agenda files]] -- [[#profiling-flet-on-a-single-file][Profiling flet on a single file]] -- [[#profiling-org-trust-scanner-tags][Profiling org-trust-scanner-tags]] -- [[#profiling-position-based][Profiling position-based]] -- [[#profiling-tags-matching][Profiling tags matching]] -- [[#using-org-element-parse-buffer][Using org-element-parse-buffer]] -- [[#withwithout-tsel][with/without ts.el]] -:END: - - -** [2019-08-29 Thu 06:24] Benchmarking org-ql compared to re-search-forward for getting headings in buffer -:PROPERTIES: -:ID: fcc09229-ed24-42eb-a1fd-31d8f7d4c8d5 -:END: - -Minimal difference, and that's a very large file, too. On smaller files it's thousandths of a second. - -#+BEGIN_SRC elisp - (with-current-buffer (find-buffer-visiting "~/org/inbox.org") - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("org-ql" (org-ql-select (current-buffer) - '(level 1) - :action '(progn - (font-lock-ensure (line-beginning-position) (line-end-position)) - (cons (org-get-heading t) (point))))) - ("re-search-forward" (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop while (re-search-forward (rx bol "*" (1+ blank)) nil t) - do (font-lock-ensure (line-beginning-position) (line-end-position)) - collect (cons (org-get-heading t) (match-beginning 0)))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------+--------------------+---------------+----------+------------------| -| re-search-forward | 1.17 | 0.520375 | 0 | 0 | -| org-ql | slowest | 0.608281 | 0 | 0 | - -** Caching of inherited tags - -[2019-09-05 Thu 07:59] Implemented a per-buffer tags cache that seems to significantly speed up tags queries that use tag inheritance. It persists as long as the buffer remains unmodified, and it's usable from any code as a single function that automatically uses caching. It also returns inherited tags and local tags separately, which could be useful for having separate selectors, one for inherited tags, one for local tags, and one for both. - -#+BEGIN_SRC elisp - (defvar org-ql-tags-cache (ht) - "Per-buffer tags cache. - Keyed by buffer. Each value is a cons of the buffer's modified - tick, and another hash table keyed on buffer position, whose - values are a list of two lists, inherited tags and local tags, as - strings.") - - (defun org-ql--tags-at (position) - "Return tags for POSITION in current buffer. - Returns cons (INHERITED-TAGS . LOCAL-TAGS)." - ;; I'd like to use `-if-let*', but it doesn't leave non-nil variables - ;; bound in the else clause, so destructured variables that are non-nil, - ;; like found caches, are not available in the else clause. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-tags-cache)) - (modified-tick (car buffer-cache)) - (tags-cache (cdr buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cached-result (gethash position tags-cache))) - ;; Found in cache: return them. - (pcase cached-result - ('org-ql-nil nil) - (_ cached-result)) - ;; Not found in cache: get tags and cache them. - (let* ((local-tags (or (org-get-tags position 'local) - 'org-ql-nil)) - (inherited-tags (or (save-excursion - (when (org-up-heading-safe) - (-let* (((inherited local) (org-ql--tags-at (point))) - (inherited-tags (when (or inherited local) - (cond ((and (listp inherited) - (listp local)) - (append inherited local)) - ((cond ((listp inherited) inherited) - ((listp local) local))))))) - (when inherited-tags - (->> inherited-tags -non-nil -uniq))))) - 'org-ql-nil)) - (all-tags (list inherited-tags local-tags))) - ;; Check caches again, because they may have been set now. - ;; TODO: Is there a clever way we could avoid doing this, or is it inherently necessary? - (setf buffer-cache (gethash (current-buffer) org-ql-tags-cache) - modified-tick (car buffer-cache) - tags-cache (cdr buffer-cache) - buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cond ((or (not buffer-cache) - (not buffer-unmodified-p)) - ;; Buffer-local tags cache empty or invalid: make new one. - (puthash (current-buffer) - (cons (buffer-modified-tick) - (let ((table (make-hash-table))) - (puthash position all-tags table) - table)) - org-ql-tags-cache) - ;; Return tags, not the cons put on the buffer-cache. - all-tags) - ;; Buffer-local tags cache found, but no result: store this one. - (t (puthash position all-tags tags-cache)))))) - - (org-ql--defpred tags-cached (&rest tags) - "Return non-nil if current heading has one or more of TAGS (a list of strings)." - ;; TODO: Try to use `org-make-tags-matcher' to improve performance. It would be nice to not have - ;; to run `org-get-tags' for every heading, especially with inheritance. - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((inherited local) (org-ql--tags-at (point)))) - (cl-typecase tags - (null (or (tags-p inherited) - (tags-p local))) - (otherwise (or (when (tags-p inherited) - (seq-intersection tags inherited)) - (when (tags-p local) - (seq-intersection tags local)))))))) -#+END_SRC - -Benchmark results: - -#+BEGIN_SRC elisp - (let* ((buffers '("~/org/main.org")) - (tags '("Emacs"))) - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("uncached" (let ((org-ql-cache (ht))) - (org-ql-select buffers - `(tags ,@tags)))) - ("cached" (let ((org-ql-cache (ht)) - (org-ql-tags-cache (ht))) - (org-ql-select buffers - `(tags-cached ,@tags))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| cached | 6.51 | 0.519871 | 0 | 0 | -| uncached | slowest | 3.386679 | 0 | 0 | - -** Intersecting query results - -An idea that /might/ be helpful for performance in /some/ cases, depending on the query, the data, and whether the query has a preamble. But it looks like it would very rarely be helpful. - -#+BEGIN_SRC elisp - (cl-defun org-ql-agenda-intersection (buffers-files queries &key entries sort buffer narrow super-groups) - "Like `org-ql-agenda', but intersects multiple queries." - (declare (indent defun)) - (let* ((org-ql-cache (ht)) - (entries (->> queries - (--map (org-ql-select buffers-files - it - :action 'element-with-markers - :narrow narrow - :sort sort)) - (-reduce #'-intersection)))) - (org-ql-agenda--agenda buffers-files queries - :entries entries :super-groups super-groups))) - - (bench-multi-lexical :times 1 - :forms (("intersection" (let ((org-use-tag-inheritance nil)) - (org-ql-agenda-intersection (org-agenda-files) - '((todo "TODO") - (tags "Emacs")) - :sort '(priority deadline) - :super-groups org-super-agenda-groups))) - ("normal" (let ((org-use-tag-inheritance nil)) - (org-ql-agenda (org-agenda-files) - (and (todo "TODO") - (tags "Emacs")) - :sort (priority deadline) - :super-groups org-super-agenda-groups))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------+--------------------+---------------+----------+------------------| -| normal | 3.70 | 0.233147 | 0 | 0 | -| intersection | slowest | 0.862512 | 0 | 0 | - -*** Alternative approach - -[2019-09-01 Sun 08:17] This is very experimental, but the results are surprising. When the action function returns a fairly simple list, the intersection is very slightly faster. When returning full elements, the intersection is much slower, so that it more than doubles the runtime. I wonder if the element list comparison is short-circuiting, or if it looks at the whole lists, because it seems like it shouldn't take more than 4-5 list elements before it realizes that two lists don't match. - -Anyway, looks like this approach isn't viable, at least not without a much more complicated implementation, which probably wouldn't be worth it. - -#+BEGIN_SRC elisp - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - ;; NOTE: Careful to use the same files and action in each one. I duplicated - ;; the variable in each form to make individual testing easier. - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (let ((org-ql-cache (ht)) - (action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn)))) - ("Testing" (let* ((org-ql-cache (ht)) - (files '("~/org/main.org")) - (action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| Testing | 1.15 | 0.248376 | 0 | 0 | -| normal | slowest | 0.284897 | 0 | 0 | - -#+BEGIN_SRC elisp - -;; With caching enabled - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn))) - ("Testing" (let* ((files '("~/org/main.org")) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 13.72 | 0.002311 | 0 | 0 | -| Testing | slowest | 0.031707 | 0 | 0 | - -Using full views: - -#+BEGIN_SRC elisp - (let* ((action-fn (lambda () - (list (current-buffer) - (point) - (substring-no-properties (org-get-heading t t))))) - (files '("~/org/main.org"))) - (bench-multi-lexical :times 1 - :forms (("normal" (->> (let ((org-ql-cache (ht)) - (files '("~/org/main.org"))) - (org-ql-search files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))))))) - ("Testing" (let* ((org-ql-cache (ht)) - (files '("~/org/main.org")) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action 'element-with-markers)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action 'element-with-markers))) - (final-results (seq-intersection and-results - (->> or-results - -uniq)))) - (org-ql-agenda--agenda nil nil - :entries final-results) - - ))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 1.74 | 0.534742 | 0 | 0 | -| Testing | slowest | 0.931897 | 0 | 0 | - -Just gathering results, but using elements: - -#+BEGIN_SRC elisp - (let* ((action-fn 'element-with-markers) - (files '("~/org/main.org"))) - ;; NOTE: Careful to use the same files and action in each one. I duplicated - ;; the variable in each form to make individual testing easier. - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("normal" (->> (let ((org-ql-cache (ht))) - (org-ql-select files - '(and (not (done)) - (or (habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - :action action-fn)))) - ("Testing" (let* ((org-ql-cache (ht)) - (and-queries '(not (done))) - (or-queries '((habit) - (deadline auto) - (scheduled :to today) - (ts-active :on today) - (closed :on today))) - (and-results (org-ql-select files - and-queries - :action action-fn)) - (or-results (cl-loop for query in or-queries - append (org-ql-select files - query - :action action-fn)))) - (seq-intersection and-results - (->> or-results - -uniq))))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------+--------------------+---------------+----------+------------------| -| normal | 2.27 | 0.314218 | 0 | 0 | -| Testing | slowest | 0.714587 | 0 | 0 | - - -** More profiling - -[2018-05-10 Thu 15:02] I think these are decent improvements. - -#+BEGIN_SRC elisp - (elp-profile 1 nil (org-agenda-ng "~/org/main.org" - (or (habit) - (and (or (date '= (org-today)) - (deadline '<=) - (scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))) - (and (todo "DONE" "CANCELLED") - (closed '= (org-today)))))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------+--------------+--------------+--------------| -| mapcar | 164 | 1.5004585290 | 0.0091491373 | -| org-agenda-ng--agenda | 1 | 1.348231247 | 1.348231247 | -| org-agenda-ng--filter-buffer | 1 | 1.1391189879 | 1.1391189879 | -| org-agenda-ng--date-plain-p | 1267 | 0.6198571040 | 0.0004892321 | -| org-entry-get | 3983 | 0.2979337370 | 7.480...e-05 | -| org-is-habit-p | 1365 | 0.2049101109 | 0.0001501172 | -| org--property-local-values | 1365 | 0.1940614150 | 0.0001421695 | -| org-agenda-ng--habit-p | 1272 | 0.1911009179 | 0.0001502365 | -| org-agenda-ng--format-element | 52 | 0.177965411 | 0.0034224117 | -| org-get-property-block | 1365 | 0.1760004519 | 0.0001289380 | -| org-get-tags-at | 52 | 0.1362824969 | 0.0026208172 | -| org-agenda-ng--date-p | 3880 | 0.1351176629 | 3.482...e-05 | -| org-up-heading-safe | 226 | 0.1276747609 | 0.0005649325 | -| re-search-backward | 2028 | 0.1144211070 | 5.642...e-05 | -| org-entry-properties | 2618 | 0.0848660999 | 3.241...e-05 | -| org-agenda-ng--todo-p | 1319 | 0.081952653 | 6.213...e-05 | -| org-get-todo-state | 1319 | 0.0796836810 | 6.041...e-05 | -| re-search-forward | 3754 | 0.0739803739 | 1.970...e-05 | -| org-inlinetask-in-task-p | 1365 | 0.0657829330 | 4.819...e-05 | -| org-agenda-ng--scheduled-p | 1247 | 0.0619497850 | 4.967...e-05 | - -** Preambles - -Not sure if clearing the cache is necessary here, because it seemed to make nearly no difference in the results, but I don't know why. - -#+BEGIN_SRC elisp :results silent - (cl-defmacro org-ql-preamble-bench (&key query (file "tests/data.org") (times 10)) - `(bench-multi-lets :times ,times :ensure-equal t - :lets (("preamble" ((org-ql-use-preamble t) - (org-ql-cache (ht)))) - ("no preamble" ((org-ql-use-preamble nil) - (org-ql-cache (ht))))) - :forms ((,(prin1-to-string query) (org-ql-select ,file - ',query - :action '(org-get-heading t t)))))) -#+END_SRC - -*** =closed= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (closed)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-----------------------+--------------------+---------------+----------+------------------| -| preamble: (closed) | 4.80 | 0.086553 | 0 | 0 | -| no preamble: (closed) | slowest | 0.415165 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (closed <= "2019-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (closed <= "2019-01-01") | 4.21 | 0.105782 | 0 | 0 | -| no preamble: (closed <= "2019-01-01") | slowest | 0.445374 | 0 | 0 | - -*** =deadline= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (deadline)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------------+--------------------+---------------+----------+------------------| -| preamble: (deadline) | 27.63 | 0.014656 | 0 | 0 | -| no preamble: (deadline) | slowest | 0.404952 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (deadline <= "2019-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-----------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (deadline <= "2019-01-01") | 27.91 | 0.014606 | 0 | 0 | -| no preamble: (deadline <= "2019-01-01") | slowest | 0.407682 | 0 | 0 | - -*** =habit= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (habit)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------+--------------------+---------------+----------+------------------| -| preamble: (habit) | 70.09 | 0.016489 | 0 | 0 | -| no preamble: (habit) | slowest | 1.155649 | 0 | 0 | - -*** =level= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (level 1)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|------------------------+--------------------+---------------+----------+------------------| -| preamble: (level 1) | 1.34 | 0.562950 | 0 | 0 | -| no preamble: (level 1) | slowest | 0.754050 | 0 | 0 | - -*** =property= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (property "agenda-group")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (property "agenda-group") | 70.44 | 0.016571 | 0 | 0 | -| no preamble: (property "agenda-group") | slowest | 1.167203 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (property "ID")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|------------------------------+--------------------+---------------+----------+------------------| -| preamble: (property "ID") | 3.51 | 0.369830 | 0 | 0 | -| no preamble: (property "ID") | slowest | 1.299684 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (property "agenda-group" "plans")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|------------------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (property "agenda-group" "plans") | 72.54 | 0.016862 | 0 | 0 | -| no preamble: (property "agenda-group" "plans") | slowest | 1.223197 | 0 | 0 | - -*** =scheduled= - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (scheduled)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------+--------------------+---------------+----------+------------------| -| preamble: (scheduled) | 4.45 | 0.100968 | 0 | 0 | -| no preamble: (scheduled) | slowest | 0.449321 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (scheduled <= "2019-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|------------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (scheduled <= "2019-01-01") | 4.13 | 0.111067 | 0 | 0 | -| no preamble: (scheduled <= "2019-01-01") | slowest | 0.458726 | 0 | 0 | - -*** =tags= - -If tag inheritance is enabled, we have to check tags on every heading. When it's disabled, we can search directly to headings with the given tags. - -#+BEGIN_SRC elisp - (let ((org-use-tag-inheritance t)) - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-----------------------------+--------------------+---------------+----------+------------------| -| no preamble: (tags "Emacs") | 1.01 | 1.899647 | 0 | 0 | -| preamble: (tags "Emacs") | slowest | 1.921799 | 0 | 0 | - -#+BEGIN_SRC elisp - (let ((org-use-tag-inheritance nil)) - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-----------------------------+--------------------+---------------+----------+------------------| -| preamble: (tags "Emacs") | 2.08 | 0.274555 | 0 | 0 | -| no preamble: (tags "Emacs") | slowest | 0.570116 | 0 | 0 | - -*** ~ts~ - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|-------------------+--------------------+---------------+----------+------------------| -| preamble: (ts) | 1.13 | 0.475646 | 0 | 0 | -| no preamble: (ts) | slowest | 0.535950 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts :from "2019-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts :from "2019-01-01") | 1.11 | 0.537445 | 0 | 0 | -| preamble: (ts :from "2019-01-01") | slowest | 0.594534 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts :from "2017-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts :from "2017-01-01") | 1.13 | 0.526891 | 0 | 0 | -| preamble: (ts :from "2017-01-01") | slowest | 0.594360 | 0 | 0 | - -Not sure why that one is slower with preamble. - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 10 - :query (ts :from "2017-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts :from "2017-01-01") | 1.04 | 0.025688 | 0 | 0 | -| preamble: (ts :from "2017-01-01") | slowest | 0.026642 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts :to "2010-01-01")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts :to "2010-01-01") | 1.10 | 0.538603 | 0 | 0 | -| preamble: (ts :to "2010-01-01") | slowest | 0.593466 | 0 | 0 | - -*** ~ts-active~ - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-a)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------------------+--------------------+---------------+----------+------------------| -| preamble: (ts-a) | 4.77 | 0.071489 | 0 | 0 | -| no preamble: (ts-a) | slowest | 0.340896 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-a :from "2017-07-06")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (ts-a :from "2017-07-06") | 1.78 | 0.188369 | 0 | 0 | -| no preamble: (ts-a :from "2017-07-06") | slowest | 0.335975 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-a :to "2017-07-06")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (ts-a :to "2017-07-06") | 4.64 | 0.075307 | 0 | 0 | -| no preamble: (ts-a :to "2017-07-06") | slowest | 0.349445 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-a :on "2017-07-06")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| preamble: (ts-a :on "2017-07-06") | 4.33 | 0.076075 | 0 | 0 | -| no preamble: (ts-a :on "2017-07-06") | slowest | 0.329106 | 0 | 0 | - -*** ~ts-inactive~ - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-i)) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|---------------------+--------------------+---------------+----------+------------------| -| preamble: (ts-i) | 1.21 | 0.459152 | 0 | 0 | -| no preamble: (ts-i) | slowest | 0.555632 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-i :from "2019-07-06")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts-i :from "2019-07-06") | 1.09 | 0.531976 | 0 | 0 | -| preamble: (ts-i :from "2019-07-06") | slowest | 0.579745 | 0 | 0 | - -#+BEGIN_SRC elisp - (org-ql-preamble-bench :times 1 - :file "~/org/inbox.org" - :query (ts-i :to "2019-07-06")) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|--------------------------------------+--------------------+---------------+----------+------------------| -| no preamble: (ts-i :to "2019-07-06") | 1.34 | 0.553428 | 0 | 0 | -| preamble: (ts-i :to "2019-07-06") | slowest | 0.743881 | 0 | 0 | - -** Profiling flet across all agenda files - -*** With flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files org-agenda-files - :pred (lambda () - (and (todo) - (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 711 25.608392569 0.0360174297 -org-agenda-ng--agenda 5 24.019318793 4.8038637586 -org-agenda-ng--filter-buffer 40 14.160293256 0.3540073313 -org-agenda-ng--date-p 21595 4.2111783960 0.0001950071 -org-agenda-finalize-entries 5 4.0930243110 0.8186048622 -org-super-agenda--filter-finalize-entries 5 3.937522006 0.7875044012 -org-agenda-ng--todo-p 37080 3.5687476730 9.624...e-05 -org-get-todo-state 37080 3.4737076600 9.368...e-05 -outline-next-heading 34625 3.4689080650 0.0001001850 -re-search-forward 42280 3.0743315830 7.271...e-05 -org-agenda-ng--format-element 1180 2.9511605820 0.0025009835 -org-element-headline-parser 1180 2.6757063699 0.0022675477 -org-super-agenda--group-items 5 2.187362092 0.4374724183 -org-super-agenda--group-dispatch 70 2.184685662 0.0312097951 -org-entry-get 22730 2.0711872869 9.112...e-05 -org-entry-properties 21595 1.8958912070 8.779...e-05 -org-super-agenda--group-tag 25 1.8498977799 0.0739959111 -org-element-timestamp-parser 3785 1.8234333229 0.0004817525 -org-parse-time-string 7560 1.7121709579 0.0002264776 -org-element--get-time-properties 1180 1.1814058020 0.0010011913 -#+end_example - -*** Without flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files org-agenda-files - :pred (lambda () - (and (org-agenda-ng--todo-p) - (or (org-agenda-ng--date-p :deadline '<= (org-today)) - (org-agenda-ng--date-p :scheduled '<= (org-today))) - (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 711 26.910164986 0.0378483333 -org-agenda-ng--agenda 5 21.012501837 4.2025003674 -org-agenda-ng--filter-buffer 40 13.751964650 0.3437991162 -org-agenda-ng--todo-p 37080 5.8788306440 0.0001585445 -org-agenda-ng--format-element 1180 4.5712275970 0.0038739216 -org-get-todo-state 37080 4.1661659069 0.0001123561 -org-agenda-ng--date-p 21595 4.1442710769 0.0001919088 -org-entry-get 22730 2.8275069239 0.0001243953 -org-entry-properties 21595 2.6558403739 0.0001229840 -outline-next-heading 34625 2.0894695999 6.034...e-05 -org-element-headline-parser 1180 1.9110445780 0.0016195293 -re-search-forward 42280 1.6994989150 4.019...e-05 -org-agenda-ng--add-faces 1180 1.6172592580 0.0013705586 -org-agenda-ng--add-scheduled-face 1180 1.607386145 0.0013621916 -org-get-tags-at 1180 1.1521010509 0.0009763568 -org-back-to-heading 64530 1.1005834200 1.705...e-05 -org-up-heading-safe 2360 1.0182265390 0.0004314519 -outline-back-to-heading 64530 1.0086056729 1.563...e-05 -org-parse-time-string 7560 0.8314918499 0.0001099856 -org-time-string-to-absolute 3780 0.8277485280 0.0002189810 -#+end_example - - -** Profiling flet on a single file - -This shows that the difference between them, if any, is so small as to be irrelevant. The convenience and clarity are a big win. - -*** With flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files "~/org/main.org" - :pred (lambda () - (and (todo) - (or (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 526 3.7898506779 0.0072050393 -org-agenda-ng--agenda 5 2.7695176850 0.5539035370 -org-agenda-ng--filter-buffer 5 1.414347774 0.2828695548 -org-agenda-ng--format-element 265 0.8871611419 0.0033477778 -org-get-tags-at 265 0.7891641319 0.0029779778 -org-up-heading-safe 1150 0.7581951110 0.0006593000 -re-search-backward 3700 0.5948686769 0.0001607753 -org-agenda-ng--todo-p 6690 0.5840980579 8.730...e-05 -org-get-todo-state 6690 0.5666448919 8.470...e-05 -org-agenda-ng--date-p 5940 0.5196037069 8.747...e-05 -org-entry-get 6195 0.4144106150 6.689...e-05 -org-entry-properties 5940 0.3640680380 6.129...e-05 -org-element-headline-parser 265 0.2810144920 0.0010604320 -outline-next-heading 6195 0.2495287770 4.027...e-05 -org-back-to-heading 14565 0.1959557380 1.345...e-05 -re-search-forward 7850 0.1933439489 2.462...e-05 -outline-back-to-heading 14565 0.1753121230 1.203...e-05 -org-outline-level 2300 0.1676228200 7.287...e-05 -org-agenda-finalize-entries 5 0.1607656930 0.0321531386 -org-super-agenda--filter-finalize-entries 5 0.1316961509 0.0263392301 -#+end_example - -*** Without flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--agenda - :files "~/org/main.org" - :pred (lambda () - (and (org-agenda-ng--todo-p) - (or (org-agenda-ng--date-p :deadline '<= (org-today)) - (org-agenda-ng--date-p :scheduled '<= (org-today))) - (not (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)))))) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 526 3.7766218089 0.0071798893 -org-agenda-ng--agenda 5 2.75718831 0.551437662 -org-agenda-ng--filter-buffer 5 1.402551392 0.2805102784 -org-agenda-ng--format-element 265 0.8864161399 0.0033449665 -org-get-tags-at 265 0.7896260759 0.0029797210 -org-up-heading-safe 1150 0.7589292910 0.0006599385 -re-search-backward 3700 0.5956338739 0.0001609821 -org-agenda-ng--todo-p 6690 0.5781650060 8.642...e-05 -org-get-todo-state 6690 0.5603983020 8.376...e-05 -org-agenda-ng--date-p 5940 0.5209897369 8.770...e-05 -org-entry-get 6195 0.4158440950 6.712...e-05 -org-entry-properties 5940 0.3640524090 6.128...e-05 -org-element-headline-parser 265 0.2810144710 0.0010604319 -outline-next-heading 6195 0.2485497380 4.012...e-05 -org-back-to-heading 14565 0.1957209180 1.343...e-05 -re-search-forward 7850 0.1927130979 2.454...e-05 -outline-back-to-heading 14565 0.1751091780 1.202...e-05 -org-outline-level 2300 0.1680958539 7.308...e-05 -org-agenda-finalize-entries 5 0.1610422239 0.0322084448 -org-super-agenda--filter-finalize-entries 5 0.132423043 0.0264846085 -#+end_example - - -** Profiling =org-trust-scanner-tags= - -[2018-05-10 Thu 12:59] Turned on =org-trust-scanner-tags=, going to try profiling again: - -#+BEGIN_SRC elisp - ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - ;; (tags "world"))) - - (elp-profile 10 nil (org-agenda-ng org-agenda-files - (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| org-agenda-ng--agenda | 10 | 44.092598282 | 4.4092598282 | -| mapcar | 282 | 40.234516707 | 0.1426755911 | -| org-agenda-ng--filter-buffer | 80 | 26.895492471 | 0.3361936558 | -| org-element-headline-parser | 3980 | 10.387614362 | 0.0026099533 | -| org-agenda-finalize-entries | 10 | 9.194458252 | 0.9194458252 | -| org-agenda-ng--tags-p | 70250 | 8.1897379849 | 0.0001165799 | -| org-agenda-ng--format-element | 3980 | 6.5944325679 | 0.0016568926 | -| outline-next-heading | 70320 | 6.1190180490 | 8.701...e-05 | -| re-search-forward | 97050 | 5.8706467829 | 6.049...e-05 | -| org-get-tags-at | 74230 | 5.4078158059 | 7.285...e-05 | -| org-super-agenda--filter-finalize-entries | 10 | 5.2320123400 | 0.5232012340 | -| org-super-agenda--group-items | 10 | 5.1260959210 | 0.5126095921 | -| org-super-agenda--group-dispatch | 130 | 5.119333624 | 0.0393794894 | -| sort | 20 | 3.8204368569 | 0.1910218428 | -| org-element--parse-objects | 6180 | 3.5386578929 | 0.0005725983 | -| org-is-habit-p | 5970 | 3.2497755920 | 0.0005443510 | -| org-entry-get | 5970 | 3.2347964049 | 0.0005418419 | -| org--property-local-values | 5970 | 3.1796357319 | 0.0005326023 | -| org-get-property-block | 5970 | 3.0767919680 | 0.0005153755 | -| org-entries-lessp | 20020 | 2.6563960079 | 0.0001326871 | - -Now trying again without it: - -#+BEGIN_SRC elisp - ;; (elp-profile 1 nil (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - ;; (tags "world"))) - - (elp-profile 10 nil (org-agenda-ng org-agenda-files - (tags "Emacs"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-------------------------------------------+--------------+--------------+--------------| -| mapcar | 1791 | 57.096304538 | 0.0318795670 | -| org-agenda-ng--agenda | 10 | 54.232133506 | 5.4232133505 | -| org-agenda-ng--filter-buffer | 80 | 30.065167040 | 0.3758145880 | -| org-get-tags-at | 74230 | 13.840202495 | 0.0001864502 | -| org-agenda-ng--format-element | 3980 | 13.429297797 | 0.0033741954 | -| org-element-headline-parser | 3980 | 12.771776652 | 0.0032089891 | -| org-agenda-finalize-entries | 10 | 9.1439433990 | 0.9143943399 | -| org-agenda-ng--tags-p | 70250 | 9.0249653730 | 0.0001284692 | -| org-super-agenda--filter-finalize-entries | 10 | 7.300515859 | 0.7300515859 | -| outline-next-heading | 70320 | 7.2384435649 | 0.0001029357 | -| org-super-agenda--group-items | 10 | 4.918585855 | 0.4918585855 | -| org-super-agenda--group-dispatch | 130 | 4.9125893509 | 0.0377891488 | -| re-search-forward | 101020 | 4.6294823850 | 4.582...e-05 | -| org-up-heading-safe | 7370 | 4.4629885620 | 0.0006055615 | -| org-is-habit-p | 5960 | 4.2772351910 | 0.0007176569 | -| org-entry-get | 5960 | 4.2595350800 | 0.0007146870 | -| org-super-agenda--group-tag | 50 | 3.8942044929 | 0.0778840898 | -| re-search-backward | 26150 | 3.3660083490 | 0.0001287192 | -| org--property-local-values | 5960 | 3.1793476329 | 0.0005334475 | -| org-get-property-block | 5960 | 3.0662425979 | 0.0005144702 | - -Wow, using =org-trust-scanner-tags= saves a /lot/ of time. - -** Profiling position-based - -*** Macro - -#+BEGIN_SRC elisp - (defmacro elp-profile (times &rest body) - (declare (indent defun)) - `(let ((prefixes '("org-" "string-" "s-" "buffer-" "append" "delq" "map" - "list" "car" "save-" "outline-" "delete-dups" - "sort" "line-" "nth" "concat" "char-to-string" - "rx-" "goto-" "when" "search-" "re-")) - output) - (dolist (prefix prefixes) - (elp-instrument-package prefix)) - (dotimes (x ,times) - ,@body) - (elp-results) - (elp-restore-all) - (point-min) - (forward-line 20) - (delete-region (point) (point-max)) - (setq output (buffer-substring-no-properties (point-min) (point-max))) - (kill-buffer) - (delete-window) - output)) -#+END_SRC - - -*** ng-flet - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--test-agenda-today)) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 121 0.1292609089 0.0010682719 -org-agenda-ng--test-agenda-today 5 0.0860146149 0.017202923 -org-agenda-ng--agenda 5 0.0858901769 0.0171780353 -org-agenda-ng--format-element 75 0.0308815090 0.0004117534 -org-agenda-ng--filter-buffer 5 0.026709027 0.0053418054 -org-agenda-ng--date-p 455 0.0210552310 4.627...e-05 -org-element-headline-parser 75 0.016209908 0.0002161321 -org-get-tags-at 75 0.008953666 0.0001193822 -org-agenda-ng--add-faces 75 0.0072834109 9.711...e-05 -org-element-timestamp-interpreter 150 0.0068781430 4.585...e-05 -org-entry-get 290 0.0060815609 2.097...e-05 -org-up-heading-safe 210 0.005708647 2.718...e-05 -org-agenda-finalize-entries 5 0.005201221 0.0010402442 -org-element-timestamp-parser 150 0.005191617 3.461078e-05 -org-entry-properties 290 0.0048787450 1.682...e-05 -org-element--get-time-properties 75 0.004112675 5.483...e-05 -org-agenda-ng--add-deadline-face 75 0.0039314910 5.241...e-05 -org-back-to-heading 725 0.0037559990 5.180...e-06 -org-agenda-ng--add-scheduled-face 75 0.0031766149 4.235...e-05 -org-parse-time-string 300 0.0031740200 1.058...e-05 -#+end_example - -*** ng-funcall - -#+BEGIN_SRC elisp - (elp-profile 5 (org-agenda-ng--test-agenda-today)) -#+END_SRC - -#+RESULTS: -#+begin_example -mapcar 121 0.1296645480 0.0010716078 -org-agenda-ng--test-agenda-today 5 0.086714029 0.0173428058 -org-agenda-ng--agenda 5 0.086584611 0.0173169222 -org-agenda-ng--format-element 75 0.0307461019 0.0004099480 -org-agenda-ng--filter-buffer 5 0.027136826 0.0054273652 -org-agenda-ng--date-p 455 0.0213037090 4.682...e-05 -org-element-headline-parser 75 0.016251755 0.0002166900 -org-get-tags-at 75 0.008959605 0.0001194614 -org-agenda-ng--add-faces 75 0.0072381410 9.650...e-05 -org-element-timestamp-interpreter 150 0.0069832960 4.655...e-05 -org-entry-get 290 0.0061220340 2.111...e-05 -org-up-heading-safe 210 0.0057036860 2.716...e-05 -org-agenda-finalize-entries 5 0.005372899 0.0010745798 -org-element-timestamp-parser 150 0.0050518689 3.367...e-05 -org-entry-properties 290 0.0049517209 1.707...e-05 -org-agenda-ng--add-deadline-face 75 0.0039273909 5.236...e-05 -org-element--get-time-properties 75 0.0039059429 5.207...e-05 -org-back-to-heading 725 0.0037793259 5.212...e-06 -org-parse-time-string 300 0.0032196259 1.073...e-05 -org-agenda-ng--add-scheduled-face 75 0.0031410580 4.188...e-05 -#+end_example - -*** orig - -Make sure to kill any existing agenda buffers first. - -#+BEGIN_SRC elisp - (elp-profile 1 (org-agenda-list nil nil 'week)) -#+END_SRC - -#+RESULTS: -#+begin_example -org-agenda-list 1 9.693596196 9.693596196 -org-agenda-get-day-entries 56 8.630330659 0.1541130474 -org-agenda-get-scheduled 56 6.6207980570 0.1182285367 -org-is-habit-p 2792 2.2907458449 0.0008204677 -org-entry-get 2798 2.287390186 0.0008175090 -org-agenda--timestamp-to-absolute 7708 2.0970420100 0.0002720604 -org-agenda-get-deadlines 56 1.6941886389 0.0302533685 -org-at-planning-p 4399 1.3993312159 0.0003181021 -org--property-local-values 2793 1.2699226760 0.0004546805 -org-get-property-block 2794 1.2182695930 0.0004360306 -org-time-string-to-absolute 7708 1.1513844880 0.0001493752 -org-inlinetask-in-task-p 6969 1.139932302 0.0001635718 -org-parse-time-string 7880 1.0635759220 0.0001349715 -org-closest-date 3864 1.0383435800 0.0002687224 -re-search-forward 15199 0.9607921779 6.321...e-05 -org-back-to-heading 12667 0.8564486210 6.761...e-05 -outline-back-to-heading 12667 0.8362207570 6.601...e-05 -line-beginning-position 10333 0.7998346869 7.740...e-05 -org-agenda-format-item 279 0.7552402350 0.0027069542 -re-search-backward 16726 0.5694224969 3.404...e-05 -#+end_example - -** Profiling tags matching - -*** ng - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (org-agenda-ng "~/org/main.org" - (tags "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|--------------------------------+--------------+--------------+--------------| -| mapcar | 4217 | 12.612716455 | 0.0029909216 | -| org-agenda-ng--agenda | 1 | 9.721410651 | 9.721410651 | -| org-get-tags-at | 1845 | 7.4793860389 | 0.0040538677 | -| org-up-heading-safe | 9361 | 6.4622674019 | 0.0006903394 | -| re-search-backward | 25001 | 5.3399866239 | 0.0002135909 | -| org-agenda-ng--filter-buffer | 1 | 4.874598854 | 4.874598854 | -| org-agenda-ng--tags-p | 1238 | 4.8067623430 | 0.0038826836 | -| org-agenda-ng--format-element | 607 | 3.6325626609 | 0.0059844524 | -| org-outline-level | 17484 | 1.0298924459 | 5.890...e-05 | -| org-add-props | 2074 | 0.8305549259 | 0.0004004604 | -| org-element-headline-parser | 607 | 0.2092664829 | 0.0003447553 | -| org-back-to-heading | 11813 | 0.1252112960 | 1.059...e-05 | -| outline-back-to-heading | 11813 | 0.1100693780 | 9.317...e-06 | -| org-end-of-subtree | 607 | 0.0721986340 | 0.0001189433 | -| outline-on-heading-p | 11813 | 0.0675261030 | 5.716...e-06 | -| outline-next-heading | 1239 | 0.0627980999 | 5.068...e-05 | -| re-search-forward | 3273 | 0.0612446620 | 1.871...e-05 | -| org-agenda-finalize-entries | 1 | 0.041846274 | 0.041846274 | -| buffer-substring-no-properties | 6329 | 0.0308716979 | 4.877...e-06 | -| line-end-position | 903 | 0.0280484950 | 3.106...e-05 | - -*** ng without inheritance - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (org-agenda-ng "~/org/main.org" - (tags "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|--------------------------------+--------------+--------------+--------------| -| mapcar | 4217 | 12.580246839 | 0.0029832219 | -| org-agenda-ng--agenda | 1 | 8.777776059 | 8.777776059 | -| org-get-tags-at | 1845 | 8.2853503299 | 0.0044907047 | -| org-up-heading-safe | 9361 | 7.2710981889 | 0.0007767437 | -| re-search-backward | 25001 | 5.3360082060 | 0.0002134317 | -| org-agenda-ng--filter-buffer | 1 | 4.865602689 | 4.865602689 | -| org-agenda-ng--tags-p | 1238 | 4.7983754310 | 0.0038759090 | -| org-agenda-ng--format-element | 607 | 3.6273825100 | 0.0059759184 | -| org-outline-level | 17484 | 1.0284417919 | 5.882...e-05 | -| org-back-to-heading | 11813 | 0.9390534479 | 7.949...e-05 | -| org-split-string | 4940 | 0.833825087 | 0.0001687905 | -| string-match | 9102 | 0.8231629100 | 9.043...e-05 | -| org-element-headline-parser | 607 | 0.2034305819 | 0.0003351409 | -| outline-back-to-heading | 11813 | 0.1096120189 | 9.278...e-06 | -| org-end-of-subtree | 607 | 0.0710802559 | 0.0001171009 | -| outline-on-heading-p | 11813 | 0.0670029359 | 5.671...e-06 | -| outline-next-heading | 1239 | 0.0622323519 | 5.022...e-05 | -| re-search-forward | 3273 | 0.0603102519 | 1.842...e-05 | -| org-agenda-finalize-entries | 1 | 0.037286496 | 0.037286496 | -| buffer-substring-no-properties | 6329 | 0.0285818689 | 4.516...e-06 | - - -*** original - -#+BEGIN_SRC elisp - (elp-profile 1 nil - (with-current-buffer "main.org" -(org-tags-view nil "computer"))) -#+END_SRC - -#+RESULTS: -| Function | Times called | Total time | Average time | -|-----------------------------+--------------+--------------+--------------| -| org-tags-view | 1 | 2.620578129 | 2.620578129 | -| org-scan-tags | 1 | 1.448883817 | 1.448883817 | -| org-agenda-format-item | 607 | 0.9273893060 | 0.0015278242 | -| org-add-props | 2042 | 0.8877267209 | 0.0004347339 | -| org-agenda-finalize | 1 | 0.144506782 | 0.144506782 | -| re-search-forward | 2154 | 0.1367046650 | 6.346...e-05 | -| string-match | 8742 | 0.1002517259 | 1.146...e-05 | -| org-get-priority | 607 | 0.0961996220 | 0.0001584837 | -| org-agenda-align-tags | 1 | 0.095166495 | 0.095166495 | -| org-agenda-prepare | 1 | 0.081724472 | 0.081724472 | -| org-outline-level | 1246 | 0.0771033170 | 6.188...e-05 | -| org-agenda-finalize-entries | 1 | 0.071707404 | 0.071707404 | -| org-agenda-prepare-buffers | 1 | 0.057903921 | 0.057903921 | -| org-get-heading | 607 | 0.0517784369 | 8.530...e-05 | -| mapcar | 3738 | 0.0418641110 | 1.119...e-05 | -| org-agenda-highlight-todo | 607 | 0.0273123070 | 4.499...e-05 | -| mapconcat | 609 | 0.024743305 | 4.062...e-05 | -| sort | 2 | 0.02117069 | 0.010585345 | -| org-activate-plain-links | 132 | 0.0203558980 | 0.0001542113 | -| org-activate-bracket-links | 78 | 0.0198589680 | 0.0002546021 | - -** Using =org-element-parse-buffer= - -This basically works, as a very basic kind of agenda view, but we can already see that it's much slower (at least, for single-day views) because =org-element-parse-buffer= is slow compared to the agenda code. - -[2018-05-10 Thu 15:03] *Note:* This is the old, much slower code that used =org-element-parse-buffer=. - -*** Macro - -#+BEGIN_SRC elisp - (defmacro elp-profile (times prefixes &rest body) - (declare (indent defun)) - (let ((prefixes (append '(org- string- s- buffer- append delq map - list car save- outline- delete-dups - sort line- nth concat char-to-string - rx- goto- when search- re-) - prefixes))) - `(let (output) - (dolist (prefix ',prefixes) - (elp-instrument-package (symbol-name prefix))) - (dotimes (x ,times) - ,@body) - (elp-results) - (elp-restore-all) - (point-min) - (forward-line 20) - (delete-region (point) (point-max)) - (setq output (buffer-substring-no-properties (point-min) (point-max))) - (kill-buffer) - (delete-window) - (let ((rows (s-lines output))) - (append (list (list "Function" "Times called" "Total time" "Average time") - 'hline) - (cl-loop for row in rows - collect (s-split (rx (1+ space)) row 'omit-nulls))))))) -#+END_SRC - -[2018-05-09 Wed 17:31] *Note*: I seem to have misplaced the =org-agenda-ng--test-agenda-today= function I used in these tests. - -*** ng - -#+BEGIN_SRC elisp - (elp-profile 1 (org-agenda-ng--test-agenda-today)) -#+END_SRC - -#+RESULTS: -#+begin_example -org-element--parse-elements 5832 18.501891926 0.0031724780 -mapcar 98 6.3412930759 0.0647070722 -org-agenda-ng--test-agenda-today 1 6.30112088 6.30112088 -org-agenda-ng--agenda-multi 1 6.301086333 6.301086333 -org-agenda-ng--get-entries 8 6.249823971 0.7812279963 -mapc 2803 5.9078545849 0.0021076898 -org-element-parse-buffer 8 4.796204625 0.5995255781 -org-element--current-element 6557 3.7164850469 0.0005667965 -org-element-headline-parser 6557 3.5548915590 0.0005421521 -org-end-of-subtree 6557 1.3663438270 0.0002083794 -org-agenda-ng--filter-tree 8 1.3661297829 0.1707662228 -org-element-map 8 1.365995685 0.1707494606 -line-end-position 9503 0.4900104040 5.156...e-05 -org-at-heading-p 12389 0.4574876539 3.692...e-05 -re-search-forward 20193 0.4566419319 2.261...e-05 -outline-on-heading-p 19286 0.4559736580 2.364...e-05 -org-outline-level 6775 0.3970647569 5.860...e-05 -org-back-to-heading 6897 0.3689033409 5.348...e-05 -outline-back-to-heading 6897 0.3587580889 5.201...e-05 -line-beginning-position 11702 0.2887473860 2.467...e-05 -#+end_example - -*** orig - -Make sure to kill any existing agenda buffers first. - -#+BEGIN_SRC elisp - (elp-profile 1 (org-agenda-list nil nil 'week)) -#+END_SRC - -#+RESULTS: -#+begin_example -org-agenda-list 1 1.717467214 1.717467214 -org-agenda-get-day-entries 7 1.124906724 0.1607009605 -org-agenda-get-scheduled 7 0.9354116170 0.1336302310 -org-get-tags-at 62 0.5598817790 0.0090303512 -org-up-heading-safe 262 0.5531687240 0.0021113310 -org-back-to-heading 2646 0.5316139889 0.0002009123 -org-agenda-finalize 1 0.485185818 0.485185818 -org-agenda-skip 749 0.4059732339 0.0005420203 -org-at-planning-p 921 0.2137141959 0.0002320458 -org-is-habit-p 574 0.1953095319 0.0003402605 -org-entry-get 579 0.195275877 0.0003372640 -org--property-local-values 574 0.1899641870 0.0003309480 -org-get-property-block 574 0.1789142650 0.0003116973 -re-search-backward 3586 0.1769497870 4.934...e-05 -org-inlinetask-in-task-p 1495 0.1639709820 0.0001096795 -outline-back-to-heading 2646 0.1387423440 5.243...e-05 -re-search-forward 3177 0.1353034909 4.258...e-05 -org-agenda-get-deadlines 7 0.1341101260 0.0191585894 -line-beginning-position 2041 0.1000089939 4.899...e-05 -org-get-todo-state 749 0.070545971 9.418...e-05 -org-agenda-prepare 1 0.052788647 0.052788647 -org-agenda-prepare-buffers 1 0.050402675 0.050402675 -org-agenda-get-timestamps 7 0.0428353419 0.0061193345 -org-agenda--timestamp-to-absolute 1498 0.0414448099 2.766...e-05 -org-time-string-to-absolute 1498 0.0385546620 2.573...e-05 -org-agenda-finalize-entries 7 0.03400573 0.0048579614 -org-super-agenda--finalize-entries 7 0.0339819269 0.0048545609 -org-outline-level 505 0.0335176070 6.637...e-05 -org-super-agenda--group-items 7 0.0268096709 0.0038299529 -org-super-agenda--group-dispatch 84 0.024216379 0.0002882902 -org-parse-time-string 1572 0.0211881319 1.347...e-05 -org-closest-date 749 0.0178231690 2.379...e-05 -org-before-first-heading-p 578 0.0142076310 2.458...e-05 -org-refresh-category-properties 1 0.013815263 0.013815263 -org-in-src-block-p 753 0.0135235599 1.795...e-05 -org-refresh-stats-properties 1 0.012230309 0.012230309 -org-habit-parse-todo 5 0.0121474539 0.0024294907 -org-get-limited-outline-regexp 1502 0.0100960829 6.721...e-06 -mapcar 309 0.009495786 3.073...e-05 -org-super-agenda--group-habit 7 0.009318616 0.0013312308 -string-match 6253 0.0090207890 1.442...e-06 -org-super-agenda--group-dispatch-and 7 0.0067444 0.0009634857 -org-agenda-get-blocks 7 0.0060974240 0.0008710605 -outline-on-heading-p 2655 0.0060741090 2.287...e-06 -org-agenda-get-sexps 7 0.0057924309 0.0008274901 -org-super-agenda--group-regexp 7 0.005592509 0.0007989298 -org-refresh-properties 2 0.005461118 0.002730559 -org-super-agenda--get-item-entry 31 0.004812809 0.0001552519 -org-agenda-align-tags 1 0.004677699 0.004677699 -org-set-regexps-and-options 1 0.004533983 0.004533983 -org--setup-collect-keywords 2 0.004499168 0.002249584 -org-agenda-format-item 31 0.0039898020 0.0001287032 -org-date-to-gregorian 420 0.0039648049 9.440...e-06 -org-agenda-highlight-todo 31 0.0039479179 0.0001273521 -string-to-number 8202 0.0031924329 3.892...e-07 -org-end-of-subtree 12 0.003047285 0.0002539404 -org-super-agenda--group-tag 35 0.002941374 8.403...e-05 -org-inlinetask-outline-regexp 1495 0.002887697 1.931...e-06 -org-get-wdays 749 0.0027946290 3.731...e-06 -org-refresh-effort-properties 1 0.002750279 0.002750279 -org-entry-beginning-position 31 0.002345909 7.567...e-05 -sort 25 0.0021000059 8.400...e-05 -mapc 445 0.0018132390 4.074...e-06 -line-end-position 72 0.00177188 2.460...e-05 -mapconcat 341 0.0016574119 4.860...e-06 -org-entries-lessp 60 0.0016203450 2.700...e-05 -concat 336 0.0016188640 4.818...e-06 -org-habit-insert-consistency-graphs 1 0.001368346 0.001368346 -org-add-props 137 0.001291149 9.424...e-06 -org-element-at-point 1 0.001266403 0.001266403 -org-agenda-new-marker 62 0.001253987 2.022...e-05 -outline-next-heading 42 0.001123596 2.675...e-05 -org-split-string 148 0.0011049120 7.465...e-06 -org-element--parse-to 1 0.001074227 0.001074227 -org-get-scheduled-time 5 0.0010200300 0.000204006 -org-super-agenda--group-todo 21 0.001003225 4.777...e-05 -org-time-string-to-time 69 0.0009947770 1.441...e-05 -org-element--current-element 4 0.0009597410 0.0002399352 -org-entry-properties 5 0.0008807149 0.0001761429 -org-at-date-range-p 172 0.0008412679 4.891...e-06 -org-agenda-mode 1 0.000787997 0.000787997 -org-super-agenda--group-log 14 0.0007874939 5.624...e-05 -buffer-substring 31 0.0007650360 2.467...e-05 -org-heading-components 9 0.00071644 7.960...e-05 -org-entry-end-position 31 0.0007046580 2.273...e-05 -string-prefix-p 789 0.0006732279 8.532...e-07 -org-agenda-skip-eval 1498 0.0006586869 4.397...e-07 -org-get-repeat 5 0.000656577 0.0001313153 -org-activate-bracket-links 3 0.000648713 0.0002162376 -org-agenda-fix-displayed-tags 31 0.000636446 2.053...e-05 -s-join 252 0.0006324150 2.509...e-06 -org-element-keyword-parser 4 0.000530311 0.0001325777 -org-in-commented-heading-p 4 0.00051077 0.0001276925 -buffer-substring-no-properties 308 0.0004763350 1.546...e-06 -org-habit-build-graph 5 0.0004689199 9.3784e-05 -car 1626 0.0004469320 2.748...e-07 -org-activate-plain-links 3 0.000382191 0.000127397 -org-super-agenda--transform-groups 7 0.0003747289 5.353...e-05 -org-get-priority 26 0.0003598600 1.384...e-05 -org-agenda-fontify-priorities 1 0.000357076 0.000357076 -org-super-agenda--group-priority 14 0.00035224 2.516e-05 -org-agenda-prepare-window 1 0.00033704 0.00033704 -org-find-text-property-in-string 316 0.0003191880 1.010...e-06 -org-not-nil 821 0.0003016530 3.674...e-07 -list 940 0.0002995150 3.186...e-07 -org-super-agenda--group-time-grid 7 0.0002954999 4.221...e-05 -org-agenda-format-date-aligned 7 0.0002794120 3.991...e-05 -org-super-agenda--get-tags 103 0.0002654610 2.577...e-06 -delq 513 0.0002634709 5.135...e-07 -org-replace-escapes 5 0.0002382050 4.7641e-05 -car-safe 911 0.0002314199 2.540...e-07 -org-today 48 0.0002232539 4.651...e-06 -org-get-time-of-day 19 0.000219044 1.152...e-05 -org-days-to-iso-week 9 0.0002125040 2.361...e-05 -append 433 0.0002083290 4.811...e-07 -org-get-category 31 0.000198604 6.406...e-06 -string-match-p 31 0.0001787880 5.767...e-06 -org-agenda-today-p 21 0.0001658670 7.898...e-06 -org-super-agenda--get-marker 54 0.0001629399 3.017...e-06 -delete-dups 111 0.0001343219 1.210...e-06 -org-at-heading-p 9 0.000128871 1.4319e-05 -string-equal 361 0.0001168969 3.238...e-07 -org-super-agenda--make-agenda-header 13 0.0001151760 8.859...e-06 -org-add-prop-inherited 142 0.0001142290 8.044...e-07 -org-check-agenda-file 8 0.000110448 1.3806e-05 -org-agenda-get-day-face 7 0.000110437 1.577...e-05 -org-get-agenda-file-buffer 8 0.000107414 1.342675e-05 -org-agenda-files 3 0.000102652 3.421...e-05 -org-downcase-keep-props 90 0.0001008230 1.120...e-06 -org-super-agenda--get-priority-cookie 15 9.460...e-05 6.307e-06 -org-get-todo-face 31 9.423...e-05 3.039...e-06 -org-find-base-buffer-visiting 8 8.7492e-05 1.09365e-05 -org-habit-get-faces 140 8.080...e-05 5.771...e-07 -org-remove-uninherited-tags 176 7.580...e-05 4.307...e-07 -goto-char 31 7.1014e-05 2.290...e-06 -org-super-agenda--transform-group-order 7 6.5543e-05 9.363...e-06 -org-agenda-add-time-grid-maybe 7 5.703...e-05 8.147...e-06 -org-compile-prefix-format 1 5.2164e-05 5.2164e-05 -org-link-unescape 4 4.4823e-05 1.120575e-05 -listp 133 3.960...e-05 2.977...e-07 -org-habit-duration-to-days 5 3.9446e-05 7.8892e-06 -org-make-options-regexp 1 3.6054e-05 3.6054e-05 -org-agenda-mark-header-line 1 3.3066e-05 3.3066e-05 -org-element--collect-affiliated-keywords 4 3.2661e-05 8.16525e-06 -org-habit-get-priority 5 2.9857e-05 5.9714e-06 -org-agenda-get-category-icon 31 2.673...e-05 8.624...e-07 -org-face-from-face-or-color 61 2.1803e-05 3.574...e-07 -org-reduced-level 40 2.1692e-05 5.423e-07 -org-link-get-parameter 26 2.062...e-05 7.930...e-07 -buffer-name 57 1.9875e-05 3.486...e-07 -org-defkey 5 1.9835e-05 3.966...e-06 -string-to-char 56 1.929...e-05 3.446...e-07 -org-string-nw-p 5 1.7894e-05 3.578...e-06 -s-wrap 7 1.6955e-05 2.422...e-06 -org-link-expand-abbrev 2 1.5491e-05 7.7455e-06 -map-keymap 2 1.4987e-05 7.4935e-06 -search-forward 7 1.403...e-05 2.004...e-06 -string-lessp 41 1.394...e-05 3.400...e-07 -org-agenda-reset-markers 1 1.3927e-05 1.3927e-05 -org-agenda-deadline-face 7 1.2592e-05 1.798...e-06 -search-backward 5 1.1253e-05 2.2506e-06 -org-agenda-span-name 5 9.758e-06 1.9516e-06 -outline-previous-heading 1 8.678e-06 8.678e-06 -buffer-modified-p 10 4.618e-06 4.617...e-07 -buffer-file-name 13 4.608...e-06 3.544...e-07 -buffer-live-p 11 4.473e-06 4.066...e-07 -buffer-local-value 10 4.278e-06 4.278...e-07 -buffer-base-buffer 10 3.858e-06 3.858...e-07 -org-agenda-set-mode-name 1 3.118e-06 3.118e-06 -org-remove-flyspell-overlays-in 4 2.926...e-06 7.315...e-07 -buffer-size 8 2.791...e-06 3.489...e-07 -org-key 5 2.707e-06 5.414e-07 -org-unbracket-string 1 2.692e-06 2.692e-06 -save-place-to-alist 1 2.276e-06 2.276e-06 -org-element--cache-put 4 1.907e-06 4.7675e-07 -org-property-inherit-p 2 1.414e-06 7.07e-07 -org-agenda-ndays-to-span 2 1.293...e-06 6.465...e-07 -maphash 1 1.171e-06 1.171e-06 -org-set-sorting-strategy 1 1.165e-06 1.165e-06 -org-file-menu-entry 1 1.12e-06 1.12e-06 -string-width 2 1.093e-06 5.465e-07 -org-time-stamp-format 1 1.054e-06 1.054e-06 -org-agenda-fit-window-to-buffer 1 9.31e-07 9.31e-07 -org-font-lock-add-tag-faces 1 9.13e-07 9.13e-07 -org-agenda-span-to-ndays 1 8.3e-07 8.3e-07 -org-element-property 2 8.12e-07 4.06e-07 -org-agenda-mark-clocking-task 1 8.03e-07 8.03e-07 -org-tag-alist-to-groups 1 7.55e-07 7.55e-07 -org-element-type 1 6.14e-07 6.14e-07 -org-agenda-use-sticky-p 1 4.73e-07 4.73e-07 -mapatoms 1 0 0.0 -#+end_example - -*** Profile org-element-map - -#+BEGIN_SRC elisp - (elp-profile 1 (with-current-buffer (find-buffer-visiting "~/org/main.org") - (org-element-parse-buffer 'headline))) -#+END_SRC - -#+RESULTS: -#+begin_example -org-element--parse-elements 1002 4.1612395469 0.0041529336 -org-element-parse-buffer 1 0.859981956 0.859981956 -org-element--current-element 1225 0.8236391779 0.0006723585 -org-element-headline-parser 1225 0.7952382879 0.0006491741 -org-end-of-subtree 1225 0.5557043549 0.0004536362 -line-end-position 1995 0.0751104350 3.764...e-05 -re-search-forward 3743 0.0516547359 1.380...e-05 -org-outline-level 1225 0.0477962079 3.901...e-05 -org-back-to-heading 1225 0.0469223529 3.830...e-05 -outline-back-to-heading 1225 0.0450936199 3.681...e-05 -org-element--get-node-properties 1225 0.0434517140 3.547...e-05 -line-beginning-position 2003 0.0334129610 1.668...e-05 -org-element--get-time-properties 1225 0.0306394040 2.501...e-05 -org-get-limited-outline-regexp 2072 0.0140703559 6.790...e-06 -org-element-timestamp-parser 249 0.0124751890 5.010...e-05 -outline-next-heading 847 0.0115396399 1.362...e-05 -org-at-heading-p 2227 0.0109473260 4.915...e-06 -outline-on-heading-p 3452 0.0101107139 2.928...e-06 -string-match 4594 0.0064121759 1.395...e-06 -mapcar 30 0.0041008740 0.0001366958 -#+end_example - -** with/without ts.el - -[2019-08-11 Sun 15:39] These results seem to show a minor performance improvement by using ~ts~, and the code is simpler. - -#+BEGIN_SRC elisp - ;; (require 'ts) - - (org-ql--defpred ts-ts (&key from to _on) - ;; The underscore before `on' prevents "unused lexical variable" warnings, because we - ;; pre-process that argument in a macro before this function is called. - "Return non-nil if current entry has a timestamp in given period. - If no arguments are specified, return non-nil if entry has any - timestamp. - - If FROM, return non-nil if entry has a timestamp on or after - FROM. - - If TO, return non-nil if entry has a timestamp on or before TO. - - If ON, return non-nil if entry has a timestamp on date ON. - - FROM, TO, and ON should be strings parseable by - `parse-time-string' but may omit the time value." - ;; TODO: DRY this with the clocked predicate. - ;; NOTE: FROM and TO are actually expected to be Unix timestamps. The docstring is written - ;; for end users, for which the arguments are pre-processed by `org-ql-select'. - ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. - (cl-macrolet ((next-timestamp () - `(when (re-search-forward org-element--timestamp-regexp end-pos t) - (ts-parse-org (match-string 0)))) - (test-timestamps (pred-form) - `(cl-loop for next-ts = (next-timestamp) - while next-ts - thereis ,pred-form))) - (save-excursion - (let ((end-pos (org-entry-end-position))) - (cond ((not (or from to)) (re-search-forward org-element--timestamp-regexp end-pos t)) - ((and from to) (test-timestamps (and (ts<= from next-ts) - (ts<= next-ts to)))) - (from (test-timestamps (ts<= from next-ts))) - (to (test-timestamps (ts<= next-ts to)))))))) - -#+END_SRC - -*** :from - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :from "2017-01-01"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :from "2017-01-01"))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.32 | 1.299966 | 0 | 0 | -| old ts | slowest | 1.713027 | 0 | 0 | - -*** :on - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :on "2019-05-14"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :on "2019-05-14"))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.17 | 0.557281 | 0 | 0 | -| old ts | slowest | 0.652149 | 0 | 0 | - -*** :to - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts :to "2019-01-01"))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts :to "2019-01-01"))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.01 | 1.300084 | 0 | 0 | -| old ts | slowest | 1.312208 | 0 | 0 | - -*** Without timestamp argument - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 1 :ensure-equal t - :forms (("old ts" (org-ql "~/org/inbox.org" - (ts))) - ("ts.el ts" (org-ql "~/org/inbox.org" - (ts-ts))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.14 | 2.251801 | 0 | 0 | -| old ts | slowest | 2.560280 | 0 | 0 | - -#+BEGIN_SRC elisp - (bench-multi-lexical :times 20 :ensure-equal t - :forms (("old ts" (org-ql "~/src/emacs/org-ql/tests/data.org" - (ts))) - ("ts.el ts" (org-ql "~/src/emacs/org-ql/tests/data.org" - (ts-ts))))) -#+END_SRC - -#+RESULTS: -| Form | x faster than next | Total runtime | # of GCs | Total GC runtime | -|----------+--------------------+---------------+----------+------------------| -| ts.el ts | 1.05 | 0.103714 | 0 | 0 | -| old ts | slowest | 0.108663 | 0 | 0 | - -* References -:PROPERTIES: -:TOC: :include descendants :depth 1 -:END: -:CONTENTS: -- [[#github---ndwarshuisorg-sql-sql-backend-for-emacs-org-mode][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] -- [[#john-kitchin-on-rewriting-the-org-agenda-code][John Kitchin on rewriting the Org agenda code]] -- [[#nicolas-goazious-org-element-cache-implementation][Nicolas Goaziou's org-element cache implementation]] -- [[#uniform-structured-syntax-metaprogramming-and-run-time-compilation][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] -:END: - -** [[https://github.com/ndwarshuis/org-sql][GitHub - ndwarshuis/org-sql: SQL backend for Emacs Org-Mode]] - -[2020-01-04 Sat 09:03] - -** [[gnus:gmane.emacs.orgmode#CAJ51EToLCm5zDLKu8XeuqEWrLhHZF+OoNkviPSivZbFttzF8=A@mail.gmail.com][John Kitchin on rewriting the Org agenda code]] :Emacs:Org: - -[2019-10-28 Mon 08:28] Originally from [[id:90a68535-2403-4ba9-a117-60be1862628f][this entry in my notes]]. - -#+BEGIN_QUOTE -From: John Kitchin -Subject: Re: [Orgmode] Slow speed of week and month views -Newsgroups: gmane.emacs.orgmode -To: Karl Voit -Cc: "emacs-orgmode@gnu.org" -Date: Sat, 5 Aug 2017 18:17:09 -0400 (4 hours, 11 minutes, 38 seconds ago) - -I can think of two possibilities for a future approach (besides a deep dive on profiling the current elisp to improve the speed there). They both involve some substantial coding though, and would probably add dependencies. I am curious what anyone things about these, or if there are other ideas. - -One is to use the new dynamic module capability to write an org parser in C, or a dedicated agenda function, which would presumably be faster than in elisp. This seems hard, and for me would certainly be a multiyear project I am sure! The downside of this is the need to compile the module. I don't know how easy it would be to make this work across platforms with the relatively easy install org-mode currently has. This could have a side benefit though of a c-lib that could be used by others to expand where org-mode is used. - -The other way that might work is to rely more heavily on a cached version of the files, perhaps in a different format than elisp, that is faster to work with. The approach I have explored in this is to index org files into a sqlite database. The idea then would be to generate the agenda from a sql query. I use something like this already to "find stuff in orgmode anywhere". One of the reasons I wrote this is the org-agenda list of files isn't practical for me because my files are so scattered on my file system. I had a need to be able to find TODOs in research projects in a pretty wide range of locations. - -The code I use is at https://github.com/jkitchin/scimax/blob/master/org-db.el, and from one database I can find headlines, contacts, locations, TODO headlines across my file system, all the files that contain a particular link, and my own recent org files. This approach relies on emacsql, and a set of hook functions to update the database whenever a file is changed. It is not robust, e.g. the file could be out of sync with the db if it is modified outside emacs, but this works well enough for me so far. Updated files get reindexed whenever emacs is idle. It was a compromise on walking the file system all the time or daily, or trying to use inotify and you can always run a command to prune/sync all the files any time you want. - -sqlite is ok, but with emacsql you cannot put strings in it directly (at least when I wrote the org-db code), which has limited it for full-text search so far. Also with text, the db got up to about 0.5 GB in size, and started slowing down. So it doesn't have text in it for now. It has all the other limitations of sqlite too, limited support for locking, single process.... - -I am moderately motivated to switch from sqlite to MongoDB, but the support for Mongo in emacs is pretty crummy (I tried writing a few traditional interfaces, but the performance was not that good, and limited since Mongo uses bson, and it is just not the same as json!). Why Mongo? Mostly because the Mongo query language is basically json and easy to generate in Emacs, unlike sql. Also, it is flexible and easy to adapt to new things, e.g. indexing src-blocks or tables or whatever org-element you want. (And I want to use Mongo for something else too ;). Obviously these all add dependencies, and might not be suitable for the core org-mode distribution. But I do think it is important to think about ways to scale org-mode while maintaining compatibility with the core. - -The main point of the database was to get a query language, persistence and good performance. I have also used caches to speed up using bibtex files, and my org-contacts with reasonable performance. These have been all elisp, with no additional dependencies. Maybe one could do something similar to keep an agenda cache that is persistent and updated via hook functions. - -Thoughts? - -John -#+END_QUOTE -:PROPERTIES: -:archive.is: http://archive.is/33R9M -:END: - -+ [[https://github.com/m00natic/cl-fdbq][GitHub - m00natic/cl-fdbq: SQL-like operations over fixed field DBs]] - -** Nicolas Goaziou's =org-element= cache implementation - -[2020-01-04 Sat 08:31] https://code.orgmode.org/bzg/org-mode/src/master/lisp/org-element.el#L4817 I guess I haven't been keeping up, because I'm not sure when exactly he made or committed this, or what his plans for it are. It's currently disabled by default. - -** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] - -* Testing - -[2020-01-08 Wed 07:15] Subtree moved from =tests/data.org=. - -#+BEGIN_SRC elisp - (cl-defun ap/org-tweak-timestamps (&key (offset 0) epoch-ts) - "Advance all timestamps in the current buffer as if the earliest one was on today. - OFFSET changes which timestamp (in chronological order) is set to - today. Or, if EPOCH-TS is non-nil, use it as the new zero-point - for today." - (let* ((tss (->> (org-with-wide-buffer - (goto-char (point-min)) - (cl-loop while (re-search-forward org-ts-regexp-both nil t) - collect (ts-parse-org (match-string 0)))) - (-sort #'ts<))) - (epoch-ts (if epoch-ts - (ts-parse-org epoch-ts) - (nth offset tss))) - (difference-secs (ts-diff (ts-now) epoch-ts)) - (days (floor (/ difference-secs 86400)))) - (org-with-wide-buffer - (goto-char (point-min)) - (while (re-search-forward org-ts-regexp-both nil t) - (let* ((ts (ts-parse-org (match-string 0))) - (timed-p (string-match-p (rx (repeat 2 digit) ":" (repeat 2 digit) (or ">" "]")) (match-string 0))) - (type (cond ((string-prefix-p "<" (match-string 0)) 'active) - ((string-prefix-p "[" (match-string 0)) 'inactive) - (t (error "Unknown ts type")))) - (brackets (cl-ecase type - ('active (cons "<" ">")) - ('inactive (cons "[" "]")))) - (format-string (concat (car brackets) - (if timed-p - "%Y-%m-%d %a %H:%M" - "%Y-%m-%d %a") - (cdr brackets))) - (new-ts (ts-adjust 'day days ts)) - (new-ts-string (ts-format format-string new-ts))) - (replace-match new-ts-string t t nil 0)))) - (message "Tweaked from epoch: %s" (ts-format epoch-ts)))) -#+END_SRC - -#+BEGIN_SRC elisp -(org-time-string-to-absolute (org-entry-get (point) "SCHEDULED")) -#+END_SRC - - #+BEGIN_SRC elisp :results none - ;; Setup code - (require 'org-super-agenda) - (org-super-agenda-mode 1) - (require 'org-habit) - (setq org-todo-keywords - '((sequence "TODO(t!)" "TODAY(a!)" "NEXT(n!)" "STARTED(s!)" "IN-PROGRESS(p!)" "UNDERWAY(u!)" "WAITING(w@)" "SOMEDAY(o!)" "MAYBE(m!)" "|" "DONE(d@)" "CANCELED(c@)") - (sequence "CHECK(k!)" "|" "DONE(d@)") - (sequence "TO-READ(r!)" "READING(R!)" "|" "HAVE-READ(d@)") - (sequence "TO-WATCH(!)" "WATCHING(!)" "SEEN(!)"))) - (with-current-buffer "test.org" (revert-buffer)) - - (defmacro with-org-today-date (date &rest body) - "Run BODY with the `org-today' function set to return simply DATE. - DATE should be a date-time string (both date and time must be included)." - (declare (indent defun)) - `(let ((day (date-to-day ,date)) - (orig (symbol-function 'org-today))) - (unwind-protect - (progn - (fset 'org-today (lambda () day)) - ,@body) - (fset 'org-today orig)))) - #+END_SRC - -#+BEGIN_SRC elisp :results none - (defun diary-sunrise () - (let ((dss (diary-sunrise-sunset))) - (with-temp-buffer - (insert dss) - (goto-char (point-min)) - (search-forward ",") - (buffer-substring (point-min) (match-beginning 0))))) - - (defun diary-sunset () - (let ((dss (diary-sunrise-sunset)) - start end) - (with-temp-buffer - (insert dss) - (goto-char (point-min)) - (search-forward ", ") - (setq start (match-end 0)) - (search-forward " at") - (setq end (match-beginning 0)) - (goto-char start) - (capitalize-word 1) - (buffer-substring start end)))) -#+END_SRC - -*Note:* Removing tests from here as they're added to =test.el=. - - #+BEGIN_SRC elisp - - (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Time grid items in all-uppercase with RosyBrown1 foreground" - :time-grid t - :transformer (--> it - (upcase it) - (propertize it 'face '(:foreground "RosyBrown1")))) - (:name "Priority >= C items underlined, on black background" - :face (:background "black" :underline t) - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - (org-super-agenda--test-with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/emacs/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name none - :time-grid t) - (:name "Should be all-uppercase RosyBrown1 on black" - :face (:background "black" :foreground "RosyBrown1") - :transformer #'upcase - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name none - :time-grid t) - (:name none - :not (:priority>= "C") - :order 100)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Items with child TODOs" - :children todo)))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:name "Items with child TODOs" - :children "CHECK")))) - (org-agenda nil "a"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Today" - :time-grid t - :scheduled today - :deadline today))))) - (todo "" ((org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Today" - :time-grid today))))) - (todo "" ((org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-agenda-custom-commands - '(("u" "Super view" - ((agenda "" ((org-super-agenda-groups - '((:name "Schedule" - :time-grid t - :date today) - (:name "Due today" - :deadline today) - (:name "Due soon" - :deadline t))))) - (todo "" ((org-agenda-overriding-header "") - (org-super-agenda-groups - '((:name "Projects" - :children t) - (:discard (:anything t))))))))))) - (org-agenda nil "u"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - (org-super-agenda-groups - '((:scheduled (before "2017-07-06"))))) - (org-agenda nil "a"))) -#+END_SRC - -#+BEGIN_SRC elisp - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "WAITING"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-todo-list))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "SOMEDAY"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-tags-view nil "Emacs"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "CHECK"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) -;; org-search-view doesn't seem to set the todo-state property, so the matcher doesn't work - (org-search-view nil "Emacs"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:regexp ("moon" "mars")))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-search-view nil "space"))) - - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:todo "SOMEDAY"))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-agenda-list nil nil 'day))) - -#+END_SRC - -** Agenda censoring - -For sharing screenshots of the agenda without revealing private data. - -#+BEGIN_SRC elisp - (defun org-agenda-sharpie () - "Censor the text of items in the agenda." - (interactive) - (let (regexp old-heading new-heading properties) - ;; Save face properties of line in agenda to reapply to changed text - (setq properties (text-properties-at (point))) - - ;; Go to source buffer - (org-with-point-at (org-find-text-property-in-string 'org-marker - (buffer-substring (line-beginning-position) - (line-end-position))) - ;; Save old heading text and ask for new text - (line-beginning-position) - (unless (org-at-heading-p) - ;; Not sure if necessary - (org-back-to-heading)) - (setq old-heading (when (looking-at org-complex-heading-regexp) - (match-string 4)))) - (setq new-heading (read-from-minibuffer "Overwrite visible heading with: ")) - (add-text-properties 0 (length new-heading) properties new-heading) - ;; Back to agenda buffer - (save-excursion - (when (and old-heading new-heading) - ;; Replace agenda text - (let ((inhibit-read-only t)) - (goto-char (line-beginning-position)) - (when (search-forward old-heading (line-end-position)) - (replace-match new-heading 'fixedcase 'literal))))))) -#+END_SRC - -** Agenda examining - -This helps a lot. - -#+BEGIN_SRC elisp - (defun data-debug-show-string-with-properties (s) - (with-current-buffer (get-buffer-create "argh") - (erase-buffer) - (print s (current-buffer)) - - ;; Convert string reader representations to plain lists that can be set - (cl-loop for (match replace) in '(("#(" "'(") - ("#<" "'(") - (">" ")")) - do (progn - (goto-char (point-min)) - (while (search-forward match nil 'noerror) - (replace-match replace 'fixedcase 'literal)))) - - ;; Surround content in a list which `argh' is set to, then eval - ;; the buffer to do it - (goto-char (point-min)) - (insert "(setq argh (list '") - (delete-forward-char 2) - (goto-char (point-max)) - (insert "))") - - ;; Okay, sure, eval'ing the buffer is dangerous and bad and wrong. - ;; But this is the only way I can find to make this work. (Maybe - ;; `text-properties-at' could be used to get actual lists...) - (eval-buffer) - - (data-debug-show-stuff argh "argh") - ;; (switch-to-buffer (current-buffer)) - )) - - (defun data-debug-show-current-line-with-properties () - (interactive) - (data-debug-show-string-with-properties (buffer-substring (line-beginning-position) (line-end-position)))) - - (with-current-buffer "*Org Agenda*" - (data-debug-show-string-with-properties (seq-subseq (split-string (buffer-string) "\n") - 0 5))) -#+END_SRC - -** Auto categories - -#+BEGIN_SRC elisp - (let ((org-super-agenda-groups - '((:auto-category t)))) - (org-agenda-list nil nil 'day)) -#+END_SRC - -** Auto grouping - - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (let ((org-super-agenda-groups - '((:auto-group t))) - (org-agenda-files (list "~/src/org-super-agenda/test/test.org"))) - (org-agenda-list nil nil 'day))) -#+END_SRC - -** Date - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) - (last-day-of-month - ;; A hack that seems to work fine - (1+ (calendar-last-day-of-month month year))) - (target-date (format "%d-%02d-%02d" year month last-day-of-month)) - (org-super-agenda-groups - `((:deadline (before ,target-date)) - (:discard (:anything t))))) - (org-todo-list))) - - (with-org-today-date "2017-07-05 00:00" - (-let* ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-agenda-span 'day) - ((sec minute hour day month year dow dst utcoff) (list 0 0 0 5 7 2017 3 t nil)) - (last-day-of-month (calendar-last-day-of-month month year)) - (target-date (format "%d-%02d-%02d" year month last-day-of-month)) - (org-super-agenda-groups - `((:deadline (before ,target-date)) - (:discard (:anything t))))) - (org-todo-list))) -#+END_SRC - -** Effort - -#+BEGIN_SRC elisp - (with-org-today-date "2017-07-05 00:00" - (let ((org-agenda-files (list "~/src/org-super-agenda/test/test.org")) - (org-super-agenda-groups - '((:effort< "0:06")))) - (org-agenda-list nil nil 'day))) -#+END_SRC - -** Misc - -*** let-plist - -I don't need this right now, but it might come in handy here or elsewhere. - -#+BEGIN_SRC elisp - (defmacro osa/let-plist (keys plist &rest body) - "`cl-destructuring-bind' without the boilerplate for plists." - ;; See https://emacs.stackexchange.com/q/22542/3871 - - ;; I really don't understand why Emacs doesn't have this already. - ;; So many things come close to it: pcase, pcase-let, map-let, - ;; cl-destructuring-bind, -let...but none of them let you simply - ;; bind all the values of a plist to variables with the same name as - ;; their keys. You always have to type the name of the key twice. - - ;; For example, compare these two forms: - - ;; (-let (((&keys :from from :to to :date date :subject subject) email)) - ;; (list from to date subject)) - - ;; (osa/let-plist (:from :to :date :subject) email - ;; (list from to date subject)) - - ;; Now, sure, sometimes you need to bind values to differently named - ;; variables. But when you don't, I know which one I prefer. - (declare (indent defun)) - (setq keys (cl-loop for key in keys - collect (intern (replace-regexp-in-string (rx bol ":") "" - (symbol-name key))))) - `(cl-destructuring-bind - (&key ,@keys &allow-other-keys) - ,plist - ,@body)) -#+END_SRC - -** Profiling - -#+BEGIN_SRC elisp :results none - (defmacro profile-it (times &rest body) - `(let (output) - (dolist (p '("org-super-agenda-" "map" "org-" "string-" "s-" "buffer-" "append" "delq" "map" "list" "car" "save-" "outline-" "delete-dups" "sort" "line-" "nth" "concat" "char-to-string" "rx-" "goto-" "when" "search-" "re-")) - (elp-instrument-package p)) - (dotimes (x ,times) - ,@body) - (elp-results) - (elp-restore-all) - (point-min) - (forward-line 20) - (delete-region (point) (point-max)) - (setq output (buffer-substring-no-properties (point-min) (point-max))) - (kill-buffer) - (delete-window) - output)) -#+END_SRC - - -* [#C] COMMENT Config :noexport: - -** File-local variables - -# Local Variables: -# before-save-hook: ((lambda () (when (fboundp 'unpackaged/org-fix-blank-lines) (unpackaged/org-fix-blank-lines t))) (lambda () (when (fboundp 'ap/org-sort-entries-recursive-multi) (save-excursion (goto-char (point-min)) (ap/org-sort-entries-recursive-multi '(?a ?p ?o))))) org-update-all-dblocks org-make-toc) -# org-ql-ask-unsafe-queries: nil -# End: - From 1a77cb0e1896573417ecca75ceeb09afb8ec888b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 18 Nov 2020 08:15:47 -0600 Subject: [PATCH 248/560] Tests: Add more sexp link tests --- tests/test-org-ql.el | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 7dad757..d297fc6 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -1514,6 +1514,42 @@ RESULTS should be a list of strings as returned by (expect (var-after-link-save-open 'org-ql-view-query temp-filenames sexp-query) :to-equal sexp-query)))) + (describe "in raw sexp form" + ;; These tests guard against manually constructed queries, which could + ;; theoretically be different than the ones resulting from storing links (i.e. they + ;; might have encoding). These tests probably aren't necessary, but it's good to + ;; be extra careful, because an evil sexp could be harmful if eval'ed. + :var ((raw-link "[[org-ql-search:(todo \"TODO\")]]")) + + (describe "prompt when `org-ql-ask-unsafe-queries' is non-nil" + :var ((org-ql-ask-unsafe-queries t)) + + (it "and signal an error when rejected by user" + (expect (open-link-in raw-link link-buffer "no RET") + :to-throw 'user-error '("Query aborted by user"))) + (it "and run when approved by user" + (expect (open-link-in raw-link link-buffer "yes RET") + :not :to-throw))) + + (it "don't prompt when `org-ql-ask-unsafe-queries' is nil" + (let ((org-ql-ask-unsafe-queries nil)) + (expect (open-link-in raw-link link-buffer "no RET") + :not :to-throw))) + + (it "match after restoring" + (let ((org-ql-ask-unsafe-queries nil) ; Disable safety check for this test. + (org-ql-view-buffer view-buffer)) + (expect (open-link-in raw-link link-buffer "no RET") + :not :to-throw) + (expect (buffer-local-value 'org-ql-view-query view-buffer) + :to-equal '(todo "TODO")))) + + (it "could be evil when not prompted about" + ;; This test confirms what *could* happen if these checks weren't in place. + (let ((org-ql-ask-unsafe-queries nil)) + (expect (open-link-in "[[org-ql-search:(error \"EVIL!\")]]" link-buffer nil) + :to-throw 'error '("EVIL!"))))) + (describe "in string form" (it "match after restoring" ;; NOTE: This test includes the string query being replaced with its sexp form after the query is run. From 0f5cf5eff320cd718d60359d4562430955719040 Mon Sep 17 00:00:00 2001 From: Ihor Radchenko Date: Sun, 12 Apr 2020 13:40:09 +0800 Subject: [PATCH 249/560] Honor restriction when it is set from inside agenda dispatcher --- org-ql-search.el | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/org-ql-search.el b/org-ql-search.el index cf49281..9f7ba3f 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -233,15 +233,14 @@ If `org-ql-block-header' is non-nil, it is used as the header string for the block, otherwise a the header is formed automatically from the query." (let (narrow-p old-beg old-end) - (when-let* ((from (pcase org-agenda-overriding-restriction + (when-let* ((from (pcase org-agenda-restrict ('nil (org-agenda-files nil 'ifmode)) - ('file (get 'org-agenda-files 'org-restrict)) - ('subtree (prog1 org-agenda-restrict - (with-current-buffer org-agenda-restrict - ;; Narrow the buffer; remember to widen it later. - (setf old-beg (point-min) old-end (point-max) - narrow-p t) - (narrow-to-region org-agenda-restrict-begin org-agenda-restrict-end)))))) + (_ (prog1 org-agenda-restrict + (with-current-buffer org-agenda-restrict + ;; Narrow the buffer; remember to widen it later. + (setf old-beg (point-min) old-end (point-max) + narrow-p t) + (narrow-to-region org-agenda-restrict-begin org-agenda-restrict-end)))))) (items (org-ql-select from query :action 'element-with-markers :narrow narrow-p))) From 038c5ae3bf5e9077989e65c186f3da8e3034de56 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 20 Nov 2020 07:54:44 -0600 Subject: [PATCH 250/560] Update changelog, version headers Released as 0.4.9. --- README.org | 5 ++ org-ql.el | 2 +- org-ql.info | 149 +++++++++++++++++++++++++++++++--------------------- 3 files changed, 95 insertions(+), 61 deletions(-) diff --git a/README.org b/README.org index 9b6b5d7..68df9aa 100644 --- a/README.org +++ b/README.org @@ -398,6 +398,11 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.4.9 + +*Fixed* ++ Agenda restriction in =org-ql-block=. (Fixes [[https://github.com/alphapapa/org-ql/issues/84][#84]]. Thanks to [[https://github.com/yantar92][Ihor Radchenko]].) + ** 0.4.8 *Fixed* diff --git a/org-ql.el b/org-ql.el index 85b47cd..2fd64fa 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.4.8 +;; Version: 0.4.9 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index 6e8a77d..a6e4465 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,8 @@ Functions / Macros Changelog +* 0.4.9: 049. +* 0.4.8: 048. * 0.4.7: 047. * 0.4.6: 046. * 0.4.5: 045. @@ -710,6 +712,8 @@ releases. * Menu: +* 0.4.9: 049. +* 0.4.8: 048. * 0.4.7: 047. * 0.4.6: 046. * 0.4.5: 045. @@ -728,9 +732,32 @@ releases. * 0.1: 01.  -File: README.info, Node: 047, Next: 046, Up: Changelog +File: README.info, Node: 049, Next: 048, Up: Changelog -5.1 0.4.7 +5.1 0.4.9 +========= + +*Fixed* + • Agenda restriction in org-ql-block. (Fixes #84 + (https://github.com/alphapapa/org-ql/issues/84). Thanks to Ihor + Radchenko (https://github.com/yantar92).) + + +File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog + +5.2 0.4.8 +========= + +*Fixed* + • Multiple sorters not preserved when refreshing views. (Fixes #136 + (https://github.com/alphapapa/org-ql/issues/136), #137 + (https://github.com/alphapapa/org-ql/pull/137). Thanks to Imran + Khan (https://github.com/natrys).) + + +File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog + +5.3 0.4.7 ========= *Fixed* @@ -743,7 +770,7 @@ File: README.info, Node: 047, Next: 046, Up: Changelog  File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog -5.2 0.4.6 +5.4 0.4.6 ========= *Fixed* @@ -756,7 +783,7 @@ File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog  File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog -5.3 0.4.5 +5.5 0.4.5 ========= *Fixed* @@ -768,7 +795,7 @@ File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog  File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog -5.4 0.4.4 +5.6 0.4.4 ========= *Fixed* @@ -780,7 +807,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.5 0.4.3 +5.7 0.4.3 ========= *Fixed* @@ -790,7 +817,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.6 0.4.2 +5.8 0.4.2 ========= *Fixed* @@ -799,7 +826,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.7 0.4.1 +5.9 0.4.1 ========= *Fixed* @@ -809,8 +836,8 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.8 0.4 -======= +5.10 0.4 +======== _Note:_ The next release, 0.5, may include changes which will require minor updates to written queries (e.g. a few predicates may be @@ -890,8 +917,8 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.9 0.3.2 -========= +5.11 0.3.2 +========== *Fixed* • In org-ql-search, accept symbol as ‘:super-groups’ argument. @@ -903,7 +930,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.10 0.3.1 +5.12 0.3.1 ========== *Fixed* @@ -913,7 +940,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.11 0.3 +5.13 0.3 ======== *Added* @@ -978,7 +1005,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.12 0.2.3 +5.14 0.2.3 ========== *Fixed* @@ -988,7 +1015,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.13 0.2.2 +5.15 0.2.2 ========== *Fixed* @@ -999,7 +1026,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.14 0.2.1 +5.16 0.2.1 ========== *Fixed* @@ -1009,7 +1036,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.15 0.2 +5.17 0.2 ======== *Added* @@ -1092,7 +1119,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.16 0.1 +5.18 0.1 ======== First tagged release. @@ -1153,47 +1180,49 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1507 -Node: Screenshots1681 -Node: Installation1799 -Node: Quelpa2437 -Node: Usage2880 -Node: Commands3229 -Node: org-ql-search3702 -Node: helm-org-ql5350 -Node: org-ql-view5762 -Node: org-ql-view-sidebar5960 -Node: org-ql-view-recent-items6316 -Node: org-ql-sparse-tree6800 -Node: Queries7600 -Node: Non-sexp query syntax8508 -Node: General predicates10215 -Node: Ancestor/descendant predicates15022 -Node: Date/time predicates16150 -Node: Functions / Macros18805 -Node: Agenda-like views19038 -Node: Listing / acting-on results20443 -Node: Changelog25045 -Node: 04725679 -Node: 04626062 -Node: 04526462 -Node: 04426821 -Node: 04327178 -Node: 04227373 -Node: 04127532 -Node: 0427771 -Node: 03231702 -Node: 03132079 -Node: 0332276 -Node: 02335251 -Node: 02235479 -Node: 02135747 -Node: 0235946 -Node: 0139981 -Node: Notes40082 -Node: Comparison with Org Agenda searches40244 -Node: org-sidebar41115 -Node: License41394 +Node: Contents1537 +Node: Screenshots1711 +Node: Installation1829 +Node: Quelpa2467 +Node: Usage2910 +Node: Commands3259 +Node: org-ql-search3732 +Node: helm-org-ql5380 +Node: org-ql-view5792 +Node: org-ql-view-sidebar5990 +Node: org-ql-view-recent-items6346 +Node: org-ql-sparse-tree6830 +Node: Queries7630 +Node: Non-sexp query syntax8538 +Node: General predicates10245 +Node: Ancestor/descendant predicates15052 +Node: Date/time predicates16180 +Node: Functions / Macros18835 +Node: Agenda-like views19068 +Node: Listing / acting-on results20473 +Node: Changelog25075 +Node: 04925739 +Node: 04826002 +Node: 04726349 +Node: 04626744 +Node: 04527144 +Node: 04427503 +Node: 04327860 +Node: 04228055 +Node: 04128214 +Node: 0428453 +Node: 03232386 +Node: 03132765 +Node: 0332962 +Node: 02335937 +Node: 02236165 +Node: 02136433 +Node: 0236632 +Node: 0140667 +Node: Notes40768 +Node: Comparison with Org Agenda searches40930 +Node: org-sidebar41801 +Node: License42080  End Tag Table From e4fb1cce2e7f41eac521fccf1367c6454b5d1154 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 20 Nov 2020 08:13:15 -0600 Subject: [PATCH 251/560] Docs: Explain how caching works Fixes #132. Thanks to Mikhail Skorzhinskii (@mskorzhinskiy) for suggesting. --- README.org | 6 +++++ org-ql.info | 73 +++++++++++++++++++++++++++++++---------------------- 2 files changed, 49 insertions(+), 30 deletions(-) diff --git a/README.org b/README.org index 0ff4d89..741e745 100644 --- a/README.org +++ b/README.org @@ -299,6 +299,12 @@ The variable =org-ql-block-header= may be bound to a string to use as the block *** Listing / acting-on results +**** Caching + +Org QL uses a per-buffer cache to speed up subsequent searches. It's keyed on query expressions, which means that, for the same query in the same buffer, if the buffer has not been modified since the last time the query was run, the cached result will be returned, and the query will not be evaluated in that buffer again. + +Therefore, since query expressions are not guaranteed to be evaluated when these functions are called, they should be free of side effects. Any side effects should be done in the action expression instead. + **** Function: ~org-ql-select~ /Arguments:/ ~(buffers-or-files query &key action narrow sort)~ diff --git a/org-ql.info b/org-ql.info index 5c9bb45..519f605 100644 --- a/org-ql.info +++ b/org-ql.info @@ -607,7 +607,20 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, 4.3.2 Listing / acting-on results --------------------------------- - 1. Function: ‘org-ql-select’ + 1. Caching + + Org QL uses a per-buffer cache to speed up subsequent searches. + It’s keyed on query expressions, which means that, for the same + query in the same buffer, if the buffer has not been modified since + the last time the query was run, the cached result will be + returned, and the query will not be evaluated in that buffer again. + + Therefore, since query expressions are not guaranteed to be + evaluated when these functions are called, they should be free of + side effects. Any side effects should be done in the action + expression instead. + + 2. Function: ‘org-ql-select’ _Arguments:_ ‘(buffers-or-files query &key action narrow sort)’ @@ -667,7 +680,7 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, '(todo "WAITING")) ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) - 2. Function: ‘org-ql-query’ + 3. Function: ‘org-ql-query’ _Arguments:_ ‘(&key (select 'element-with-markers) from where order-by narrow)’ @@ -712,7 +725,7 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, :where '(todo "WAITING")) ;; => ((headline (:raw-value "Visit the moon" ...) ...) ...) - 3. Macro: ‘org-ql’ + 4. Macro: ‘org-ql’ _Arguments:_ ‘(buffers-or-files query &key sort narrow markers action)’ @@ -1336,33 +1349,33 @@ Node: Date/time predicates17145 Node: Functions / Macros19800 Node: Agenda-like views20055 Node: Listing / acting-on results21460 -Node: Dynamic block26062 -Node: Links28760 -Node: Tips29447 -Node: Changelog29765 -Node: 05-pre30449 -Node: 04931688 -Node: 04831966 -Node: 04732313 -Node: 04632708 -Node: 04533108 -Node: 04433467 -Node: 04333824 -Node: 04234019 -Node: 04134178 -Node: 0434419 -Node: 03238352 -Node: 03138731 -Node: 0338928 -Node: 02341903 -Node: 02242131 -Node: 02142399 -Node: 0242598 -Node: 0146633 -Node: Notes46734 -Node: Comparison with Org Agenda searches46896 -Node: org-sidebar47768 -Node: License48047 +Node: Dynamic block26655 +Node: Links29353 +Node: Tips30040 +Node: Changelog30358 +Node: 05-pre31042 +Node: 04932281 +Node: 04832559 +Node: 04732906 +Node: 04633301 +Node: 04533701 +Node: 04434060 +Node: 04334417 +Node: 04234612 +Node: 04134771 +Node: 0435012 +Node: 03238945 +Node: 03139324 +Node: 0339521 +Node: 02342496 +Node: 02242724 +Node: 02142992 +Node: 0243191 +Node: 0147226 +Node: Notes47327 +Node: Comparison with Org Agenda searches47489 +Node: org-sidebar48361 +Node: License48640  End Tag Table From 6bb2db93921e70293fb2f73f6cfe51811a9b28db Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 20 Nov 2020 08:22:41 -0600 Subject: [PATCH 252/560] Docs: Improve query explanation See #92. --- README.org | 2 +- org-ql.info | 79 +++++++++++++++++++++++++++-------------------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/README.org b/README.org index 741e745..2d7f300 100644 --- a/README.org +++ b/README.org @@ -165,7 +165,7 @@ Show a sparse tree for ~QUERY~ in ~BUFFER~ and return number of results. The tr - [[#datetime-predicates][Date/time predicates]] :END: -An =org-ql= query is a lisp form which may contain arbitrary lisp forms, as well as certain built-in predicates. It is byte-compiled into a predicate function which is tested with point on each heading in an Org buffer; when it returns non-nil, the heading matches the query. +An =org-ql= query is a Lisp expression which may contain arbitrary expressions, as well as calling certain built-in predicates. It is byte-compiled into a predicate function which is tested with point on each heading in an Org buffer; when it returns non-nil, the heading matches the query. When possible, certain built-in predicates are optimized away to whole-buffer regular expression searches, which are much faster to search for than testing the predicate on each heading. *Notes:* + Bare strings like ~"string"~ are automatically converted to ~(regexp "string")~ predicates. diff --git a/org-ql.info b/org-ql.info index 519f605..da41319 100644 --- a/org-ql.info +++ b/org-ql.info @@ -318,10 +318,13 @@ File: README.info, Node: Queries, Next: Functions / Macros, Prev: Commands, =========== • • • • - An org-ql query is a lisp form which may contain arbitrary lisp -forms, as well as certain built-in predicates. It is byte-compiled into -a predicate function which is tested with point on each heading in an -Org buffer; when it returns non-nil, the heading matches the query. + An org-ql query is a Lisp expression which may contain arbitrary +expressions, as well as calling certain built-in predicates. It is +byte-compiled into a predicate function which is tested with point on +each heading in an Org buffer; when it returns non-nil, the heading +matches the query. When possible, certain built-in predicates are +optimized away to whole-buffer regular expression searches, which are +much faster to search for than testing the predicate on each heading. *Notes:* • Bare strings like ‘"string"’ are automatically converted to @@ -1342,40 +1345,40 @@ Node: org-ql-view-sidebar6349 Node: org-ql-view-recent-items6705 Node: org-ql-sparse-tree7189 Node: Queries7989 -Node: Non-sexp query syntax8897 -Node: General predicates10604 -Node: Ancestor/descendant predicates16017 -Node: Date/time predicates17145 -Node: Functions / Macros19800 -Node: Agenda-like views20055 -Node: Listing / acting-on results21460 -Node: Dynamic block26655 -Node: Links29353 -Node: Tips30040 -Node: Changelog30358 -Node: 05-pre31042 -Node: 04932281 -Node: 04832559 -Node: 04732906 -Node: 04633301 -Node: 04533701 -Node: 04434060 -Node: 04334417 -Node: 04234612 -Node: 04134771 -Node: 0435012 -Node: 03238945 -Node: 03139324 -Node: 0339521 -Node: 02342496 -Node: 02242724 -Node: 02142992 -Node: 0243191 -Node: 0147226 -Node: Notes47327 -Node: Comparison with Org Agenda searches47489 -Node: org-sidebar48361 -Node: License48640 +Node: Non-sexp query syntax9100 +Node: General predicates10807 +Node: Ancestor/descendant predicates16220 +Node: Date/time predicates17348 +Node: Functions / Macros20003 +Node: Agenda-like views20258 +Node: Listing / acting-on results21663 +Node: Dynamic block26858 +Node: Links29556 +Node: Tips30243 +Node: Changelog30561 +Node: 05-pre31245 +Node: 04932484 +Node: 04832762 +Node: 04733109 +Node: 04633504 +Node: 04533904 +Node: 04434263 +Node: 04334620 +Node: 04234815 +Node: 04134974 +Node: 0435215 +Node: 03239148 +Node: 03139527 +Node: 0339724 +Node: 02342699 +Node: 02242927 +Node: 02143195 +Node: 0243394 +Node: 0147429 +Node: Notes47530 +Node: Comparison with Org Agenda searches47692 +Node: org-sidebar48564 +Node: License48843  End Tag Table From 2aa8e84fc999cd1e90f9ae0008dfbe7865876f5a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:09:36 -0600 Subject: [PATCH 253/560] Fix: peg-related compiler warnings --- org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 9dad848..ccf63fd 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1731,8 +1731,8 @@ element should be a regexp string." ;; Fix compiler warnings probably caused by `peg' not using lexical-binding. ;; TODO: File bug report upstream. -(defvar peg-errors nil) -(defvar peg-stack nil) +(defvar peg-errors) +(defvar peg-stack) (defmacro org-ql--peg-parse-string (rules string &optional noerror) "Parse STRING according to RULES." From 46ad26f1a02b7a6f3d0badbe9a148def7c0d914a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:20:12 -0600 Subject: [PATCH 254/560] Change: Require org-super-agenda 1.2 Which includes the safety checks we use for links. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index ccf63fd..f3d89e7 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql ;; Version: 0.5-pre -;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2-pre") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: From c41cd4be822434ba360540e563a5b9f379886b85 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:25:04 -0600 Subject: [PATCH 255/560] Change: (-view--link-open, -view--link-follow) Rename function For consistency with Org's naming scheme. --- org-ql-view.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 089baf6..0bc1b97 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -578,7 +578,7 @@ dates in the past, and negative for dates in the future." ;; than `org-ql-view' saved views, the link type is "org-ql-search". (org-link-set-parameters "org-ql-search" - :follow #'org-ql-view--link-open + :follow #'org-ql-view--link-follow :store #'org-ql-view--link-store) ;; We require the URL libraries in the functions to hopefully avoid @@ -588,7 +588,7 @@ dates in the past, and negative for dates in the future." (require 'url-parse) (require 'url-util)) -(defun org-ql-view--link-open (path) +(defun org-ql-view--link-follow (path) "Open Org QL query for current buffer at PATH. PATH should be the part of an \"org-ql-search:\" URL after the protocol. See, e.g. `org-ql-view--link-store'." From 7f8328a87c8c9fdacb4458243a0a9338206db0bd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:25:59 -0600 Subject: [PATCH 256/560] Change: (-view--link-follow) Ignore second argument Hopefully this allows compatibility with Org 9.4, since Org's news file doesn't say what the second argument is. --- org-ql-view.el | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/org-ql-view.el b/org-ql-view.el index 0bc1b97..b954fc0 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -588,10 +588,13 @@ dates in the past, and negative for dates in the future." (require 'url-parse) (require 'url-util)) -(defun org-ql-view--link-follow (path) +(defun org-ql-view--link-follow (path &optional _ignored) "Open Org QL query for current buffer at PATH. PATH should be the part of an \"org-ql-search:\" URL after the -protocol. See, e.g. `org-ql-view--link-store'." +protocol. See, e.g. `org-ql-view--link-store'. + +The optional, second argument is temporarily _IGNORED for +purposes of compatibility with changes in Org 9.4." (require 'url-parse) (require 'url-util) (when (version<= "9.3" (org-version)) From 56a08208e571b9e23e90110909fcc5937e1997c9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:31:15 -0600 Subject: [PATCH 257/560] Change: (defgroup org-ql) Add Info manual link --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index f3d89e7..1ef99fe 100644 --- a/org-ql.el +++ b/org-ql.el @@ -134,7 +134,7 @@ This list should not contain any duplicates.")) (defgroup org-ql nil "Customization for `org-ql'." :group 'org - ;; TODO: Add info manual link. + :link '(custom-manual "(org-ql)Usage") :link '(url-link "https://github.com/alphapapa/org-ql")) (defcustom org-ql-ask-unsafe-queries t From 90f712aba9ea386d7bb65f9300ddc4527c1d000d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 17:33:46 -0600 Subject: [PATCH 258/560] Change: (org-ql) Declare macro obsolete --- README.org | 3 + org-ql.el | 4 +- org-ql.info | 50 ++--- tests/test-org-ql.el | 437 ++++++++++++++++++++++--------------------- 4 files changed, 252 insertions(+), 242 deletions(-) diff --git a/README.org b/README.org index 2d7f300..fed38c4 100644 --- a/README.org +++ b/README.org @@ -478,6 +478,9 @@ Simple links may also be written manually in either sexp or non-sexp form, like: *Internal* + When formatting entries for Org QL View buffers, use internal function for retrieving heading tags. This improves speed by using our cache, and it removes the need for a compatibility alias for Org versions before 9.3. +*Deprecated* ++ Macro =org-ql= is marked obsolete. It will be removed in v0.7. Functions =org-ql-select= and =org-ql-query= should be used instead. (The macro serves only to confuse with regard to quoting arguments.) + *Acknowledgments* + [[https://github.com/tpeacock19][tpeacock19]] for extensive help testing new features in this version. diff --git a/org-ql.el b/org-ql.el index 1ef99fe..3e38088 100644 --- a/org-ql.el +++ b/org-ql.el @@ -184,12 +184,12 @@ match." (push (list :name ',pred-name :aliases ',aliases :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates)) (cl-defun ,fn-name ,args ,docstring ,@body)))) -;; TODO: Mark as obsolete/deprecated. ;;;###autoload (cl-defmacro org-ql (buffers-or-files query &key sort narrow action) "Expands into a call to `org-ql-select' with the same arguments. For convenience, arguments should be unquoted." - (declare (indent defun)) + (declare (indent defun) + (obsolete "Please use functions `org-ql-select' or `org-ql-query' instead" "org-ql 0.5")) `(org-ql-select ,buffers-or-files ',query :action ',action diff --git a/org-ql.info b/org-ql.info index da41319..3e8c933 100644 --- a/org-ql.info +++ b/org-ql.info @@ -882,6 +882,12 @@ File: README.info, Node: 05-pre, Next: 049, Up: Changelog our cache, and it removes the need for a compatibility alias for Org versions before 9.3. + *Deprecated* + • Macro org-ql is marked obsolete. It will be removed in v0.7. + Functions org-ql-select and org-ql-query should be used instead. + (The macro serves only to confuse with regard to quoting + arguments.) + *Acknowledgments* • tpeacock19 (https://github.com/tpeacock19) for extensive help testing new features in this version. @@ -1357,28 +1363,28 @@ Node: Links29556 Node: Tips30243 Node: Changelog30561 Node: 05-pre31245 -Node: 04932484 -Node: 04832762 -Node: 04733109 -Node: 04633504 -Node: 04533904 -Node: 04434263 -Node: 04334620 -Node: 04234815 -Node: 04134974 -Node: 0435215 -Node: 03239148 -Node: 03139527 -Node: 0339724 -Node: 02342699 -Node: 02242927 -Node: 02143195 -Node: 0243394 -Node: 0147429 -Node: Notes47530 -Node: Comparison with Org Agenda searches47692 -Node: org-sidebar48564 -Node: License48843 +Node: 04932719 +Node: 04832997 +Node: 04733344 +Node: 04633739 +Node: 04534139 +Node: 04434498 +Node: 04334855 +Node: 04235050 +Node: 04135209 +Node: 0435450 +Node: 03239383 +Node: 03139762 +Node: 0339959 +Node: 02342934 +Node: 02243162 +Node: 02143430 +Node: 0243629 +Node: 0147664 +Node: Notes47765 +Node: Comparison with Org Agenda searches47927 +Node: org-sidebar48799 +Node: License49078  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index d297fc6..c9d560e 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -54,14 +54,14 @@ Set at runtime by test suite.") (_ nil))) (result (pcase sexp (`(org-ql-expect ,args) - (org-ql-test--format-result--ql `(org-ql org-ql-test-buffer + (org-ql-test--format-result--ql `(org-ql-select org-ql-test-buffer ,@args :action (org-ql-test-org-get-heading)))) (`(org-ql-expect ,args ,_ :buffer ,buffer) - (org-ql-test--format-result--ql `(org-ql ,buffer + (org-ql-test--format-result--ql `(org-ql-select ,buffer ,@args :action (org-ql-test-org-get-heading)))) - (`(org-ql . _) (org-ql-test--format-result--ql sexp)) + (`(org-ql-select . _) (org-ql-test--format-result--ql sexp)) (`(org-ql--query-preamble . _) (org-ql-test--format-result--query-preamble sexp)) (`(org-ql--pre-process-query . _) (format "'%S" (eval sexp))) (_ nil)))) @@ -92,7 +92,7 @@ Set at runtime by test suite.") (interactive) (if-let* ((sexp (elisp--preceding-sexp)) (sexp (pcase sexp - (`(org-ql . ,_) (setf (car sexp) 'org-ql-agenda)) + (`(org-ql-select . ,_) (setf (car sexp) 'org-ql-agenda)) (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-search org-ql-test-buffer ',@ql-args))) (_ nil)))) @@ -131,9 +131,9 @@ Based on Buttercup macro `it'." RESULTS should be a list of strings as returned by `org-ql-test-org-get-heading'." (declare (indent defun)) - `(expect (org-ql ,buffer + `(expect (org-ql-select ,buffer ,@ql-args - :action (org-ql-test-org-get-heading)) + :action '(org-ql-test-org-get-heading)) :to-equal ,results)) (defmacro org-ql-then (&rest body) @@ -201,6 +201,7 @@ RESULTS should be a list of strings as returned by (describe "Query functions/macros" (it "org-ql" + ;; FIXME: Remove when org-ql macro is removed. (expect (length (org-ql org-ql-test-buffer (category) :sort deadline)) @@ -422,423 +423,423 @@ RESULTS should be a list of strings as returned by (describe "(ancestors)" (org-ql-it "without sub-query" - (org-ql-expect ((ancestors)) + (org-ql-expect ('(ancestors)) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((ancestors (heading "universe"))) + (org-ql-expect ('(ancestors (heading "universe"))) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(parent)" (org-ql-it "without sub-query" - (org-ql-expect ((parent)) + (org-ql-expect ('(parent)) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with sub-query" - (org-ql-expect ((parent (and (todo) (priority "A")))) + (org-ql-expect ('(parent (and (todo) (priority "A")))) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(category)" (org-ql-it "without arguments" - (expect (length (org-ql org-ql-test-buffer - (category))) + (expect (length (org-ql-select org-ql-test-buffer + '(category))) :to-equal org-ql-test-num-headings)) (org-ql-it "with a category" - (org-ql-expect ((category "ambition")) + (org-ql-expect ('(category "ambition")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")))) (describe "(children)" (org-ql-it "without arguments" - (org-ql-expect ((children)) + (org-ql-expect ('(children)) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((children (todo "CHECK"))) + (org-ql-expect ('(children (todo "CHECK"))) '("Recurring"))) (org-ql-it "with grandchildren query" ;; It's really cool how this works. It's so simple. - (org-ql-expect ((children (children "moon"))) + (org-ql-expect ('(children (children "moon"))) '("Take over the universe")))) (describe "(descendants)" (org-ql-it "without arguments" - (org-ql-expect ((descendants)) + (org-ql-expect ('(descendants)) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas"))) (org-ql-it "with sub-query" - (org-ql-expect ((descendants (todo "CHECK"))) + (org-ql-expect ('(descendants (todo "CHECK"))) '("Recurring"))) (org-ql-it "with granddescendants query" - (org-ql-expect ((descendants (descendants "moon"))) + (org-ql-expect ('(descendants (descendants "moon"))) '("Take over the universe"))) (org-ql-it "with query that should not match parent" ;; This test would fail if the `descendants' predicate did not properly exclude ;; the parent heading by narrowing the buffer to begin at the first child. - (org-ql-expect ((and (descendants (todo "WAITING")) - (not (descendants (todo "TODO" "NEXT"))))) + (org-ql-expect ('(and (descendants (todo "WAITING")) + (not (descendants (todo "TODO" "NEXT"))))) '("Take over the moon")))) (describe "(clocked)" (org-ql-it "without arguments" - (org-ql-expect ((clocked)) + (org-ql-expect ('(clocked)) '("Learn universal sign language"))) (org-ql-it "with a number" (org-ql-then - (org-ql-expect ((clocked 10)) + (org-ql-expect ('(clocked 10)) '("Learn universal sign language")))) (org-ql-it ":from a timestamp" - (org-ql-expect ((clocked :from "2017-07-05")) + (org-ql-expect ('(clocked :from "2017-07-05")) '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06")) + (org-ql-expect ('(clocked :from "2017-07-06")) nil)) (org-ql-it ":from today" (org-ql-then - (org-ql-expect ((clocked :from today)) + (org-ql-expect ('(clocked :from today)) '("Learn universal sign language")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((clocked :to "2017-07-05")) + (org-ql-expect ('(clocked :to "2017-07-05")) '("Learn universal sign language")) - (org-ql-expect ((clocked :to "2017-07-04")) + (org-ql-expect ('(clocked :to "2017-07-04")) nil)) (org-ql-it ":to today" (org-ql-then - (org-ql-expect ((clocked :to today)) + (org-ql-expect ('(clocked :to today)) '("Learn universal sign language")))) (org-ql-it ":on a date" - (org-ql-expect ((clocked :on "2017-07-05")) + (org-ql-expect ('(clocked :on "2017-07-05")) '("Learn universal sign language")) - (org-ql-expect ((clocked :on "2018-12-02")) + (org-ql-expect ('(clocked :on "2018-12-02")) nil)) (org-ql-it ":on today" (org-ql-then - (org-ql-expect ((clocked :on today)) + (org-ql-expect ('(clocked :on today)) '("Learn universal sign language")))) (org-ql-it "within a range (:from and :to)" - (org-ql-expect ((clocked :from "2017-07-04" :to "2018-12-11")) + (org-ql-expect ('(clocked :from "2017-07-04" :to "2018-12-11")) '("Learn universal sign language")) - (org-ql-expect ((clocked :from "2017-07-06" :to "2018-12-11")) + (org-ql-expect ('(clocked :from "2017-07-06" :to "2018-12-11")) nil) - (org-ql-expect ((clocked :from "2017-07-01" :to "2017-07-04")) + (org-ql-expect ('(clocked :from "2017-07-01" :to "2017-07-04")) nil))) (describe "(closed)" (org-ql-it "without arguments" - (org-ql-expect ((closed)) + (org-ql-expect ('(closed)) '("Learn universal sign language"))) (org-ql-it "with a number" (org-ql-then - (org-ql-expect ((closed 10)) + (org-ql-expect ('(closed 10)) '("Learn universal sign language")))) (org-ql-it ":on" - (org-ql-expect ((closed :on "2017-07-05")) + (org-ql-expect ('(closed :on "2017-07-05")) '("Learn universal sign language")) (org-ql-then - (org-ql-expect ((closed :on today)) + (org-ql-expect ('(closed :on today)) '("Learn universal sign language"))) - (org-ql-expect ((closed :on "2019-06-09")) + (org-ql-expect ('(closed :on "2019-06-09")) nil)) (org-ql-it ":from" - (org-ql-expect ((closed :from "2017-07-04")) + (org-ql-expect ('(closed :from "2017-07-04")) '("Learn universal sign language")) - (org-ql-expect ((closed :from "2017-07-05")) + (org-ql-expect ('(closed :from "2017-07-05")) '("Learn universal sign language")) (org-ql-then - (org-ql-expect ((closed :from today)) + (org-ql-expect ('(closed :from today)) '("Learn universal sign language"))) - (org-ql-expect ((closed :from "2017-07-06")) + (org-ql-expect ('(closed :from "2017-07-06")) nil)) (org-ql-it ":to" - (org-ql-expect ((closed :to "2017-07-04")) + (org-ql-expect ('(closed :to "2017-07-04")) nil) - (org-ql-expect ((closed :to "2017-07-05")) + (org-ql-expect ('(closed :to "2017-07-05")) '("Learn universal sign language")) (org-ql-then - (org-ql-expect ((closed :to today)) + (org-ql-expect ('(closed :to today)) '("Learn universal sign language"))) - (org-ql-expect ((closed :to "2017-07-06")) + (org-ql-expect ('(closed :to "2017-07-06")) '("Learn universal sign language")))) (describe "(deadline)" (org-ql-it "without arguments" - (org-ql-expect ((deadline)) + (org-ql-expect ('(deadline)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) (org-ql-it "auto" (org-ql-then - (org-ql-expect ((deadline auto)) + (org-ql-expect ('(deadline auto)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it "with a number" (org-ql-then - (org-ql-expect ((deadline 2)) + (org-ql-expect ('(deadline 2)) '("Take over the world" "/r/emacs")))) (org-ql-it ":on" - (org-ql-expect ((deadline :on "2017-07-05")) + (org-ql-expect ('(deadline :on "2017-07-05")) '("/r/emacs")) (org-ql-then - (org-ql-expect ((deadline :on today)) + (org-ql-expect ('(deadline :on today)) '("/r/emacs"))) - (org-ql-expect ((deadline :on "2019-06-09")) + (org-ql-expect ('(deadline :on "2019-06-09")) nil)) (org-ql-it ":from" - (org-ql-expect ((deadline :from "2017-07-04")) + (org-ql-expect ('(deadline :from "2017-07-04")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-05")) + (org-ql-expect ('(deadline :from "2017-07-05")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (org-ql-expect ((deadline :from "2017-07-06")) + (org-ql-expect ('(deadline :from "2017-07-06")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((deadline :from "2018-07-06")) + (org-ql-expect ('(deadline :from "2018-07-06")) nil) (org-ql-then - (org-ql-expect ((deadline :from today)) + (org-ql-expect ('(deadline :from today)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) (org-ql-it ":to" - (org-ql-expect ((deadline :to "2017-07-04")) + (org-ql-expect ('(deadline :to "2017-07-04")) nil) - (org-ql-expect ((deadline :to "2017-07-05")) + (org-ql-expect ('(deadline :to "2017-07-05")) '("/r/emacs")) - (org-ql-expect ((deadline :to "2018-07-06")) + (org-ql-expect ('(deadline :to "2018-07-06")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) (org-ql-then - (org-ql-expect ((deadline :to today)) + (org-ql-expect ('(deadline :to today)) '("/r/emacs"))))) (org-ql-it "(done)" - (org-ql-expect ((done)) + (org-ql-expect ('(done)) '("Learn universal sign language"))) (org-ql-it "(habit)" - (org-ql-expect ((habit)) + (org-ql-expect ('(habit)) '("Practice leaping tall buildings in a single bound"))) (describe "(heading)" (org-ql-it "with one argument" - (org-ql-expect ((heading "world")) + (org-ql-expect ('(heading "world")) ;; NOTE: This--correctly--does not match the "Skype with president of ;; Antarctica" heading, which has the tag ":world:" in its heading line. '("Take over the world"))) (org-ql-it "with two arguments" - (org-ql-expect ((heading "Take over" "world")) + (org-ql-expect ('(heading "Take over" "world")) '("Take over the world")))) (describe "(link)" (org-ql-it "without arguments" - (org-ql-expect ((link)) + (org-ql-expect ('(link)) '("/r/emacs"))) (org-ql-it "with description-or-target" - (org-ql-expect ((link "emacs")) + (org-ql-expect ('(link "emacs")) '("/r/emacs"))) (org-ql-it "with :description" - (org-ql-expect ((link :description "emacs")) + (org-ql-expect ('(link :description "emacs")) '("/r/emacs"))) (org-ql-it "with :target" - (org-ql-expect ((link :target "reddit.com")) + (org-ql-expect ('(link :target "reddit.com")) '("/r/emacs"))) (org-ql-it "with :description and :target" - (org-ql-expect ((link :description "emacs" :target "reddit.com")) + (org-ql-expect ('(link :description "emacs" :target "reddit.com")) '("/r/emacs")))) (describe "(outline-path)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path "symphony")) + (org-ql-expect ('(outline-path "symphony")) '("Write a symphony"))) (org-ql-it "with two arguments" - (org-ql-expect ((outline-path "idea" "symphony")) + (org-ql-expect ('(outline-path "idea" "symphony")) '("Write a symphony")))) (describe "(outline-path-segment)" (org-ql-it "with one argument" - (org-ql-expect ((outline-path-segment "symphony")) + (org-ql-expect ('(outline-path-segment "symphony")) '("Write a symphony"))) (org-ql-it "with a contiguous segment" - (org-ql-expect ((outline-path-segment "idea" "symphony")) + (org-ql-expect ('(outline-path-segment "idea" "symphony")) '("Write a symphony"))) (org-ql-it "with a non-contiguous segment" - (org-ql-expect ((outline-path-segment "data" "symphony")) + (org-ql-expect ('(outline-path-segment "data" "symphony")) nil))) (describe "(path)" (org-ql-it "without arguments" - (org-ql-expect ((path)) + (org-ql-expect ('(path)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with one argument" - (org-ql-expect ((path "data")) + (org-ql-expect ('(path "data")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two matching arguments" - (org-ql-expect ((path "data" "tests")) + (org-ql-expect ('(path "data" "tests")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with two arguments, one matching" - (org-ql-expect ((path "data" "nope")) + (org-ql-expect ('(path "data" "nope")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(planning)" (org-ql-it "without arguments" - (org-ql-expect ((planning)) + (org-ql-expect ('(planning)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" (org-ql-then - (org-ql-expect ((planning 2)) + (org-ql-expect ('(planning 2)) '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on" - (org-ql-expect ((planning :on "2017-07-05")) + (org-ql-expect ('(planning :on "2017-07-05")) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :on "2019-06-09")) + (org-ql-expect ('(planning :on "2019-06-09")) nil) (org-ql-then - (org-ql-expect ((planning :on today)) + (org-ql-expect ('(planning :on today)) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((planning :from "2017-07-04")) + (org-ql-expect ('(planning :from "2017-07-04")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-05")) + (org-ql-expect ('(planning :from "2017-07-05")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :from "2017-07-06")) + (org-ql-expect ('(planning :from "2017-07-06")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) (org-ql-then - (org-ql-expect ((planning :from today)) + (org-ql-expect ('(planning :from today)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((planning :to "2017-07-04")) + (org-ql-expect ('(planning :to "2017-07-04")) '("Skype with president of Antarctica")) - (org-ql-expect ((planning :to "2017-07-05")) + (org-ql-expect ('(planning :to "2017-07-05")) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((planning :to "2018-07-06")) + (org-ql-expect ('(planning :to "2018-07-06")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-then - (org-ql-expect ((planning :to today)) + (org-ql-expect ('(planning :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) (describe "(priority)" (org-ql-it "without arguments" - (org-ql-expect ((priority)) + (org-ql-expect ('(priority)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor"))) (org-ql-it "with a priority" - (org-ql-expect ((priority "A")) + (org-ql-expect ('(priority "A")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "= a priority" - (org-ql-expect ((priority = "A")) + (org-ql-expect ('(priority = "A")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it "< a priority" - (org-ql-expect ((priority < "B")) + (org-ql-expect ('(priority < "B")) '("Take over the moon" "Get haircut"))) (org-ql-it "<= a priority" - (org-ql-expect ((priority <= "B")) + (org-ql-expect ('(priority <= "B")) '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor"))) (org-ql-it "> a priority" - (org-ql-expect ((priority > "B")) + (org-ql-expect ('(priority > "B")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease"))) (org-ql-it ">= a priority" - (org-ql-expect ((priority >= "B")) + (org-ql-expect ('(priority >= "B")) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))) (describe "(property)" ;; MAYBE: Add support for (property) without arguments. ;; (org-ql-it "without arguments" - ;; (org-ql-expect ((property)))) + ;; (org-ql-expect ('(property)))) (org-ql-it "with a property" - (org-ql-expect ((property "agenda-group")) + (org-ql-expect ('(property "agenda-group")) '("Take over the universe" "Spaceship lease" "Recurring" "Write a symphony"))) (org-ql-it "with a property and a value" - (org-ql-expect ((property "agenda-group" "plans")) + (org-ql-expect ('(property "agenda-group" "plans")) '("Take over the universe" "Write a symphony")))) (describe "(regexp)" (org-ql-it "with 1 argument" - (org-ql-expect ((regexp "Take over") - :sort todo) + (org-ql-expect ('(regexp "Take over") + :sort 'todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((regexp "Take over" "universe") - :sort todo) + (org-ql-expect ('(regexp "Take over" "universe") + :sort 'todo) '("Take over the universe"))) (org-ql-it "with a plain string" (org-ql-expect ("Take over" - :sort todo) + :sort 'todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "with two plain strings in an OR" - (org-ql-expect ((or "Take over" "universe") - :sort todo) + (org-ql-expect ('(or "Take over" "universe") + :sort 'todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) (org-ql-it "case-folding predicate with non-case-folding preamble" ;; e.g. the (todo) predicate disables case-folding in its preamble, but that ;; should not prevent case-folding in this and other predicates (issue #114). - (org-ql-expect ((and (todo "TODO") (regexp "take over")) - :sort todo) + (org-ql-expect ('(and (todo "TODO") (regexp "take over")) + :sort 'todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut")))) (describe "(scheduled)" (org-ql-it "without arguments" - (org-ql-expect ((scheduled)) + (org-ql-expect ('(scheduled)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it "with a number" (org-ql-then ;; Using -1 is the easiest way to exclude some results but not all for testing this. - (org-ql-expect ((scheduled -1)) + (org-ql-expect ('(scheduled -1)) '("Skype with president of Antarctica")))) (org-ql-it ":on" - (org-ql-expect ((scheduled :on "2017-07-05")) + (org-ql-expect ('(scheduled :on "2017-07-05")) '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :on "2019-06-09")) + (org-ql-expect ('(scheduled :on "2019-06-09")) nil) (org-ql-then - (org-ql-expect ((scheduled :on today)) + (org-ql-expect ('(scheduled :on today)) '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from" - (org-ql-expect ((scheduled :from "2017-07-04")) + (org-ql-expect ('(scheduled :from "2017-07-04")) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-05")) + (org-ql-expect ('(scheduled :from "2017-07-05")) '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :from "2017-07-06")) + (org-ql-expect ('(scheduled :from "2017-07-06")) nil) (org-ql-then - (org-ql-expect ((scheduled :from today)) + (org-ql-expect ('(scheduled :from today)) '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to" - (org-ql-expect ((scheduled :to "2017-07-04")) + (org-ql-expect ('(scheduled :to "2017-07-04")) '("Skype with president of Antarctica")) - (org-ql-expect ((scheduled :to "2017-07-05")) + (org-ql-expect ('(scheduled :to "2017-07-05")) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((scheduled :to "2018-07-06")) + (org-ql-expect ('(scheduled :to "2018-07-06")) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp")) (org-ql-then - (org-ql-expect ((scheduled :to today)) + (org-ql-expect ('(scheduled :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) ;; TODO: Test (src) predicate. That will require modifying test data, which will be a @@ -847,147 +848,147 @@ RESULTS should be a list of strings as returned by (describe "(todo)" (org-ql-it "without arguments" - (org-ql-expect ((todo) - :sort todo) + (org-ql-expect ('(todo) + :sort 'todo) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 1 argument" - (org-ql-expect ((todo "WAITING") - :sort todo) + (org-ql-expect ('(todo "WAITING") + :sort 'todo) '("Visit the moon"))) (org-ql-it "with 2 arguments" - (org-ql-expect ((todo "WAITING" "SOMEDAY") - :sort todo) + (org-ql-expect ('(todo "WAITING" "SOMEDAY") + :sort 'todo) '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(tags)" (org-ql-it "without arguments" - (org-ql-expect ((tags)) + (org-ql-expect ('(tags)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (tags))) + (org-ql-expect ('(not (tags))) '("Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags "Emacs")) + (org-ql-expect ('(tags "Emacs")) '("/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs"))) + (org-ql-expect ('(not (tags "Emacs"))) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((tags "Emacs" "space")) + (org-ql-expect ('(tags "Emacs" "space")) '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags "Emacs" "space"))) + (org-ql-expect ('(not (tags "Emacs" "space"))) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags "food")) + (org-ql-expect ('(tags "food")) '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags "fruit")) + (org-ql-expect ('(tags "fruit")) '("Fruit" "Blueberry" "Strawberry") :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-inherited)" (org-ql-it "without arguments" - (org-ql-expect ((tags-inherited)) + (org-ql-expect ('(tags-inherited)) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (inherited-tags))) + (org-ql-expect ('(not (inherited-tags))) '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-inherited "Emacs")) + (org-ql-expect ('(tags-inherited "Emacs")) nil) - (org-ql-expect ((itags "ambition")) + (org-ql-expect ('(itags "ambition")) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language")) - (org-ql-expect ((not (tags-i "ambition"))) + (org-ql-expect ('(not (tags-i "ambition"))) '("Take over the universe" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((itags "personal" "world")) + (org-ql-expect ('(itags "personal" "world")) '("Skype with president of Antarctica")) - (org-ql-expect ((not (tags-inherited "personal" "world"))) + (org-ql-expect ('(not (tags-inherited "personal" "world"))) ;; Note that this correctly includes the task "Practice leaping...", which has the LOCAL tag "personal". '("Take over the universe" "Take over the world" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-inherited "food")) + (org-ql-expect ('(tags-inherited "food")) '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-inherited "fruit")) + (org-ql-expect ('(tags-inherited "fruit")) '("Blueberry" "Strawberry") :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-local)" (org-ql-it "without arguments" - (org-ql-expect ((tags-local)) + (org-ql-expect ('(tags-local)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (local-tags))) + (org-ql-expect ('(not (local-tags))) '("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag" - (org-ql-expect ((tags-local "world")) + (org-ql-expect ('(tags-local "world")) '("Take over the world" "Skype with president of Antarctica")) - (org-ql-expect ((ltags "ambition")) + (org-ql-expect ('(ltags "ambition")) '("Take over the universe")) - (org-ql-expect ((not (tags-l "ambition"))) + (org-ql-expect ('(not (tags-l "ambition"))) '("Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with 2 tags" - (org-ql-expect ((ltags "personal" "world")) + (org-ql-expect ('(ltags "personal" "world")) '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Get haircut")) - (org-ql-expect ((not (tags-local "personal" "world"))) + (org-ql-expect ('(not (tags-local "personal" "world"))) '("Take over the universe" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "/r/emacs" "Shop for groceries" "Sunrise/sunset" "Ideas" "Rewrite Emacs in Common Lisp" "Write a symphony"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-local "food")) + (org-ql-expect ('(tags-local "food")) nil :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags-local "fruit")) + (org-ql-expect ('(tags-local "fruit")) '("Fruit") :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-all), (tags&)" (org-ql-it "with 2 tags" - (org-ql-expect ((tags-all "universe" "personal")) + (org-ql-expect ('(tags-all "universe" "personal")) '("Practice leaping tall buildings in a single bound")) - (org-ql-expect ((tags& "ambition" "space")) + (org-ql-expect ('(tags& "ambition" "space")) '("Visit Mars" "Visit the moon"))) (org-ql-it "with file tags" - (org-ql-expect ((tags-all "food" "fruit")) + (org-ql-expect ('(tags-all "food" "fruit")) '("Fruit" "Blueberry" "Strawberry") :buffer (org-ql-test-data-buffer "data2.org")))) (describe "(tags-regexp), (tags*)" (org-ql-it "without arguments" - (org-ql-expect ((tags-regexp)) + (org-ql-expect ('(tags-regexp)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp" "Write a symphony")) - (org-ql-expect ((not (tags*))) + (org-ql-expect ('(not (tags*))) '("Recurring" "Sunrise/sunset" "Ideas"))) (org-ql-it "with a tag regexp" - (org-ql-expect ((tags-regexp "Emac")) + (org-ql-expect ('(tags-regexp "Emac")) '("/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags* "Emac"))) + (org-ql-expect ('(not (tags* "Emac"))) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Visit Mars" "Take over the moon" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with 2 tag regexps" - (org-ql-expect ((tags-regexp "Emac" "spac")) + (org-ql-expect ('(tags-regexp "Emac" "spac")) '("Visit Mars" "Visit the moon" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((not (tags* "Emac" "spac"))) + (org-ql-expect ('(not (tags* "Emac" "spac"))) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Take over the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Recurring" "Shop for groceries" "Sunrise/sunset" "Ideas" "Write a symphony"))) (org-ql-it "with regexp matching file tags" - (org-ql-expect ((tags-regexp "foo")) + (org-ql-expect ('(tags-regexp "foo")) '("Fruit" "Blueberry" "Strawberry" "Vegetable" "Broccoli" "Potato") :buffer (org-ql-test-data-buffer "data2.org")) - (org-ql-expect ((tags* "frui")) + (org-ql-expect ('(tags* "frui")) '("Fruit" "Blueberry" "Strawberry") :buffer (org-ql-test-data-buffer "data2.org")))) @@ -996,166 +997,166 @@ RESULTS should be a list of strings as returned by (describe "active" (org-ql-it "without arguments" - (org-ql-expect ((ts :type active)) + (org-ql-expect ('(ts :type active)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-08" :type active)) + (org-ql-expect ('(ts :from "2017-07-08" :type active)) '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (org-ql-expect ((ts :from "2019-06-08" :type active)) + (org-ql-expect ('(ts :from "2019-06-08" :type active)) nil) (org-ql-then - (org-ql-expect ((ts :from today)) + (org-ql-expect ('(ts :from today)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then - (org-ql-expect ((ts :from 5)) + (org-ql-expect ('(ts :from 5)) '("Take over the universe" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type active)) + (org-ql-expect ('(ts :to "2019-06-10" :type active)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type active)) + (org-ql-expect ('(ts :to "2017-07-04" :type active)) '("Skype with president of Antarctica")) (org-ql-then - (org-ql-expect ((ts :to today)) + (org-ql-expect ('(ts :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" (org-ql-then - (org-ql-expect ((ts :to -1)) + (org-ql-expect ('(ts :to -1)) '("Skype with president of Antarctica")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type active)) + (org-ql-expect ('(ts :on "2017-07-05" :type active)) '("Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09" :type active)) + (org-ql-expect ('(ts :on "2019-06-09" :type active)) nil) (org-ql-then - (org-ql-expect ((ts :on today)) + (org-ql-expect ('(ts :on today)) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" (org-ql-then - (org-ql-expect ((ts-active :on 2)) + (org-ql-expect ('(ts-active :on 2)) '("Take over the world"))))) (describe "inactive" (org-ql-it "without arguments" - (org-ql-expect ((ts :type inactive)) + (org-ql-expect ('(ts :type inactive)) '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-06" :type inactive)) + (org-ql-expect ('(ts :from "2017-07-06" :type inactive)) '("Visit the moon" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08" :type inactive)) + (org-ql-expect ('(ts :from "2019-06-08" :type inactive)) nil) (org-ql-then - (org-ql-expect ((ts-inactive :from today)) + (org-ql-expect ('(ts-inactive :from today)) '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then - (org-ql-expect ((ts-i :from 5)) + (org-ql-expect ('(ts-i :from 5)) '("Visit the moon" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10" :type inactive)) + (org-ql-expect ('(ts :to "2019-06-10" :type inactive)) '("Visit the moon" "Learn universal sign language" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04" :type inactive)) + (org-ql-expect ('(ts :to "2017-07-04" :type inactive)) 'nil) (org-ql-then - (org-ql-expect ((ts-inactive :to today)) + (org-ql-expect ('(ts-inactive :to today)) '("Learn universal sign language")))) (org-ql-it ":to a number of days" (org-ql-then - (org-ql-expect ((ts-i :to 5)) + (org-ql-expect ('(ts-i :to 5)) '("Learn universal sign language")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05" :type inactive)) + (org-ql-expect ('(ts :on "2017-07-05" :type inactive)) '("Learn universal sign language")) - (org-ql-expect ((ts :on "2019-06-09" :type inactive)) + (org-ql-expect ('(ts :on "2019-06-09" :type inactive)) nil) (org-ql-then - (org-ql-expect ((ts-inactive :on today)) + (org-ql-expect ('(ts-inactive :on today)) '("Learn universal sign language")))) (org-ql-it ":on a number of days" (org-ql-then - (org-ql-expect ((ts-inactive :on 19)) + (org-ql-expect ('(ts-inactive :on 19)) '("Visit the moon" "Rewrite Emacs in Common Lisp"))))) (describe "both" (org-ql-it "without arguments" - (org-ql-expect ((ts)) + (org-ql-expect ('(ts)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :type both)) + (org-ql-expect ('(ts :type both)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp"))) (org-ql-it ":from a timestamp" - (org-ql-expect ((ts :from "2017-07-05")) + (org-ql-expect ('(ts :from "2017-07-05")) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2017-07-05" :type both)) + (org-ql-expect ('(ts :from "2017-07-05" :type both)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :from "2019-06-08")) + (org-ql-expect ('(ts :from "2019-06-08")) nil) - (org-ql-expect ((ts :from "2019-06-08" :type both)) + (org-ql-expect ('(ts :from "2019-06-08" :type both)) nil) (org-ql-then - (org-ql-expect ((ts :from today)) + (org-ql-expect ('(ts :from today)) '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":from a number of days" (org-ql-then - (org-ql-expect ((ts :from -5)) + (org-ql-expect ('(ts :from -5)) '("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Visit Mars" "Visit the moon" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Internet" "Spaceship lease" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a timestamp" - (org-ql-expect ((ts :to "2017-07-06")) + (org-ql-expect ('(ts :to "2017-07-06")) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-06" :type both)) + (org-ql-expect ('(ts :to "2017-07-06" :type both)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :to "2017-07-04")) + (org-ql-expect ('(ts :to "2017-07-04")) '("Skype with president of Antarctica")) - (org-ql-expect ((ts :to "2017-07-04" :type both)) + (org-ql-expect ('(ts :to "2017-07-04" :type both)) '("Skype with president of Antarctica")) (org-ql-then - (org-ql-expect ((ts :to today)) + (org-ql-expect ('(ts :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":to a number of days" (org-ql-then - (org-ql-expect ((ts :to 5)) + (org-ql-expect ('(ts :to 5)) '("Take over the world" "Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Renew membership in supervillain club" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a timestamp" - (org-ql-expect ((ts :on "2017-07-05")) + (org-ql-expect ('(ts :on "2017-07-05")) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2017-07-05" :type both)) + (org-ql-expect ('(ts :on "2017-07-05" :type both)) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")) - (org-ql-expect ((ts :on "2019-06-09")) + (org-ql-expect ('(ts :on "2019-06-09")) nil) - (org-ql-expect ((ts :on "2019-06-09" :type both)) + (org-ql-expect ('(ts :on "2019-06-09" :type both)) nil) (org-ql-then - (org-ql-expect ((ts :on today)) + (org-ql-expect ('(ts :on today)) '("Practice leaping tall buildings in a single bound" "Learn universal sign language" "Order a pizza" "Get haircut" "Fix flux capacitor" "/r/emacs" "Shop for groceries" "Rewrite Emacs in Common Lisp")))) (org-ql-it ":on a number of days" (org-ql-then - (org-ql-expect ((ts :on 5)) + (org-ql-expect ('(ts :on 5)) '("Renew membership in supervillain club")))))) (describe "Compound queries" (org-ql-it "Tags and to-do" - (org-ql-expect ((and (todo "SOMEDAY") - (tags "Emacs"))) + (org-ql-expect ('(and (todo "SOMEDAY") + (tags "Emacs"))) '("Rewrite Emacs in Common Lisp"))))) (describe "Org link safety" @@ -1469,7 +1470,7 @@ RESULTS should be a list of strings as returned by :super-groups super-groups :sort sort :title title :buffer view-buffer) (with-current-buffer view-buffer - (cl-assert (member '("org-ql-search" :follow org-ql-view--link-open :store org-ql-view--link-store) + (cl-assert (member '("org-ql-search" :follow org-ql-view--link-follow :store org-ql-view--link-store) org-link-parameters) t) (with-simulated-input store-input From 3924b023e0f1e8fa93cfa79bdd71f9f0c0fb4679 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 18:19:02 -0600 Subject: [PATCH 259/560] Release: 0.5 --- README.org | 2 +- org-ql.el | 2 +- org-ql.info | 106 ++++++++++++++++++++++++++-------------------------- 3 files changed, 55 insertions(+), 55 deletions(-) diff --git a/README.org b/README.org index fed38c4..b3e7e42 100644 --- a/README.org +++ b/README.org @@ -461,7 +461,7 @@ Simple links may also be written manually in either sexp or non-sexp form, like: /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. -** 0.5-pre +** 0.5 *Added* + View dispatcher using =transient.el= (like Magit), bound to =v= in search/view buffers. diff --git a/org-ql.el b/org-ql.el index 3e38088..70fefe0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.5-pre +;; Version: 0.5 ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index 3e8c933..60d0048 100644 --- a/org-ql.info +++ b/org-ql.info @@ -66,7 +66,7 @@ Functions / Macros Changelog -* 0.5-pre: 05-pre. +* 0.5: 05. * 0.4.9: 049. * 0.4.8: 048. * 0.4.7: 047. @@ -831,7 +831,7 @@ releases. * Menu: -* 0.5-pre: 05-pre. +* 0.5: 05. * 0.4.9: 049. * 0.4.8: 048. * 0.4.7: 047. @@ -852,10 +852,10 @@ releases. * 0.1: 01.  -File: README.info, Node: 05-pre, Next: 049, Up: Changelog +File: README.info, Node: 05, Next: 049, Up: Changelog -5.1 0.5-pre -=========== +5.1 0.5 +======= *Added* • View dispatcher using transient.el (like Magit), bound to v in @@ -893,7 +893,7 @@ File: README.info, Node: 05-pre, Next: 049, Up: Changelog testing new features in this version.  -File: README.info, Node: 049, Next: 048, Prev: 05-pre, Up: Changelog +File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog 5.2 0.4.9 ========= @@ -1338,53 +1338,53 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1594 -Node: Screenshots1717 -Node: Installation1835 -Node: Quelpa2473 -Node: Usage2916 -Node: Commands3314 -Node: org-ql-search3787 -Node: helm-org-ql5437 -Node: org-ql-view5849 -Node: org-ql-view-sidebar6349 -Node: org-ql-view-recent-items6705 -Node: org-ql-sparse-tree7189 -Node: Queries7989 -Node: Non-sexp query syntax9100 -Node: General predicates10807 -Node: Ancestor/descendant predicates16220 -Node: Date/time predicates17348 -Node: Functions / Macros20003 -Node: Agenda-like views20258 -Node: Listing / acting-on results21663 -Node: Dynamic block26858 -Node: Links29556 -Node: Tips30243 -Node: Changelog30561 -Node: 05-pre31245 -Node: 04932719 -Node: 04832997 -Node: 04733344 -Node: 04633739 -Node: 04534139 -Node: 04434498 -Node: 04334855 -Node: 04235050 -Node: 04135209 -Node: 0435450 -Node: 03239383 -Node: 03139762 -Node: 0339959 -Node: 02342934 -Node: 02243162 -Node: 02143430 -Node: 0243629 -Node: 0147664 -Node: Notes47765 -Node: Comparison with Org Agenda searches47927 -Node: org-sidebar48799 -Node: License49078 +Node: Contents1586 +Node: Screenshots1709 +Node: Installation1827 +Node: Quelpa2465 +Node: Usage2908 +Node: Commands3306 +Node: org-ql-search3779 +Node: helm-org-ql5429 +Node: org-ql-view5841 +Node: org-ql-view-sidebar6341 +Node: org-ql-view-recent-items6697 +Node: org-ql-sparse-tree7181 +Node: Queries7981 +Node: Non-sexp query syntax9092 +Node: General predicates10799 +Node: Ancestor/descendant predicates16212 +Node: Date/time predicates17340 +Node: Functions / Macros19995 +Node: Agenda-like views20250 +Node: Listing / acting-on results21655 +Node: Dynamic block26850 +Node: Links29548 +Node: Tips30235 +Node: Changelog30553 +Node: 0531229 +Node: 04932691 +Node: 04832965 +Node: 04733312 +Node: 04633707 +Node: 04534107 +Node: 04434466 +Node: 04334823 +Node: 04235018 +Node: 04135177 +Node: 0435418 +Node: 03239351 +Node: 03139730 +Node: 0339927 +Node: 02342902 +Node: 02243130 +Node: 02143398 +Node: 0243597 +Node: 0147632 +Node: Notes47733 +Node: Comparison with Org Agenda searches47895 +Node: org-sidebar48767 +Node: License49046  End Tag Table From 148a193ca09289fb4c394f30297a6698856bf56e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 22 Nov 2020 19:06:16 -0600 Subject: [PATCH 260/560] Meta: 0.6-pre --- README.org | 4 ++ org-ql.el | 2 +- org-ql.info | 147 ++++++++++++++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 69 deletions(-) diff --git a/README.org b/README.org index b3e7e42..b4f8596 100644 --- a/README.org +++ b/README.org @@ -461,6 +461,10 @@ Simple links may also be written manually in either sexp or non-sexp form, like: /Note:/ Breaking changes may be made before version 1.0, but in the event of major changes, attempts at backward compatibility will be made with obsolescence declarations, translation of arguments, etc. Users who need stability guarantees before 1.0 may choose to use tagged stable releases. +** 0.6-pre + +Nothing new yet. + ** 0.5 *Added* diff --git a/org-ql.el b/org-ql.el index 70fefe0..bd53108 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql -;; Version: 0.5 +;; Version: 0.6-pre ;; Package-Requires: ((emacs "26.1") (dash "2.13") (dash-functional "1.2.0") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2") (ov "1.0.6") (peg "0.6") (s "1.12.0") (transient "0.1") (ts "0.2-pre")) ;; Keywords: hypermedia, outlines, Org, agenda diff --git a/org-ql.info b/org-ql.info index 60d0048..abfce7a 100644 --- a/org-ql.info +++ b/org-ql.info @@ -66,6 +66,7 @@ Functions / Macros Changelog +* 0.6-pre: 06-pre. * 0.5: 05. * 0.4.9: 049. * 0.4.8: 048. @@ -831,6 +832,7 @@ releases. * Menu: +* 0.6-pre: 06-pre. * 0.5: 05. * 0.4.9: 049. * 0.4.8: 048. @@ -852,9 +854,17 @@ releases. * 0.1: 01.  -File: README.info, Node: 05, Next: 049, Up: Changelog +File: README.info, Node: 06-pre, Next: 05, Up: Changelog -5.1 0.5 +5.1 0.6-pre +=========== + +Nothing new yet. + + +File: README.info, Node: 05, Next: 049, Prev: 06-pre, Up: Changelog + +5.2 0.5 ======= *Added* @@ -895,7 +905,7 @@ File: README.info, Node: 05, Next: 049, Up: Changelog  File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog -5.2 0.4.9 +5.3 0.4.9 ========= *Fixed* @@ -906,7 +916,7 @@ File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog  File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog -5.3 0.4.8 +5.4 0.4.8 ========= *Fixed* @@ -918,7 +928,7 @@ File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog  File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog -5.4 0.4.7 +5.5 0.4.7 ========= *Fixed* @@ -931,7 +941,7 @@ File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog  File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog -5.5 0.4.6 +5.6 0.4.6 ========= *Fixed* @@ -944,7 +954,7 @@ File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog  File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog -5.6 0.4.5 +5.7 0.4.5 ========= *Fixed* @@ -956,7 +966,7 @@ File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog  File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog -5.7 0.4.4 +5.8 0.4.4 ========= *Fixed* @@ -968,7 +978,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.8 0.4.3 +5.9 0.4.3 ========= *Fixed* @@ -978,8 +988,8 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.9 0.4.2 -========= +5.10 0.4.2 +========== *Fixed* • Items’ to-do keywords were not shown in views. @@ -987,7 +997,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.10 0.4.1 +5.11 0.4.1 ========== *Fixed* @@ -997,7 +1007,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.11 0.4 +5.12 0.4 ======== _Note:_ The next release, 0.5, may include changes which will require @@ -1078,7 +1088,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.12 0.3.2 +5.13 0.3.2 ========== *Fixed* @@ -1091,7 +1101,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.13 0.3.1 +5.14 0.3.1 ========== *Fixed* @@ -1101,7 +1111,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.14 0.3 +5.15 0.3 ======== *Added* @@ -1166,7 +1176,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.15 0.2.3 +5.16 0.2.3 ========== *Fixed* @@ -1176,7 +1186,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.16 0.2.2 +5.17 0.2.2 ========== *Fixed* @@ -1187,7 +1197,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.17 0.2.1 +5.18 0.2.1 ========== *Fixed* @@ -1197,7 +1207,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.18 0.2 +5.19 0.2 ======== *Added* @@ -1280,7 +1290,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.19 0.1 +5.20 0.1 ======== First tagged release. @@ -1338,53 +1348,54 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1586 -Node: Screenshots1709 -Node: Installation1827 -Node: Quelpa2465 -Node: Usage2908 -Node: Commands3306 -Node: org-ql-search3779 -Node: helm-org-ql5429 -Node: org-ql-view5841 -Node: org-ql-view-sidebar6341 -Node: org-ql-view-recent-items6697 -Node: org-ql-sparse-tree7181 -Node: Queries7981 -Node: Non-sexp query syntax9092 -Node: General predicates10799 -Node: Ancestor/descendant predicates16212 -Node: Date/time predicates17340 -Node: Functions / Macros19995 -Node: Agenda-like views20250 -Node: Listing / acting-on results21655 -Node: Dynamic block26850 -Node: Links29548 -Node: Tips30235 -Node: Changelog30553 -Node: 0531229 -Node: 04932691 -Node: 04832965 -Node: 04733312 -Node: 04633707 -Node: 04534107 -Node: 04434466 -Node: 04334823 -Node: 04235018 -Node: 04135177 -Node: 0435418 -Node: 03239351 -Node: 03139730 -Node: 0339927 -Node: 02342902 -Node: 02243130 -Node: 02143398 -Node: 0243597 -Node: 0147632 -Node: Notes47733 -Node: Comparison with Org Agenda searches47895 -Node: org-sidebar48767 -Node: License49046 +Node: Contents1606 +Node: Screenshots1729 +Node: Installation1847 +Node: Quelpa2485 +Node: Usage2928 +Node: Commands3326 +Node: org-ql-search3799 +Node: helm-org-ql5449 +Node: org-ql-view5861 +Node: org-ql-view-sidebar6361 +Node: org-ql-view-recent-items6717 +Node: org-ql-sparse-tree7201 +Node: Queries8001 +Node: Non-sexp query syntax9112 +Node: General predicates10819 +Node: Ancestor/descendant predicates16232 +Node: Date/time predicates17360 +Node: Functions / Macros20015 +Node: Agenda-like views20270 +Node: Listing / acting-on results21675 +Node: Dynamic block26870 +Node: Links29568 +Node: Tips30255 +Node: Changelog30573 +Node: 06-pre31269 +Node: 0531375 +Node: 04932852 +Node: 04833126 +Node: 04733473 +Node: 04633868 +Node: 04534268 +Node: 04434627 +Node: 04334984 +Node: 04235179 +Node: 04135340 +Node: 0435581 +Node: 03239514 +Node: 03139893 +Node: 0340090 +Node: 02343065 +Node: 02243293 +Node: 02143561 +Node: 0243760 +Node: 0147795 +Node: Notes47896 +Node: Comparison with Org Agenda searches48058 +Node: org-sidebar48930 +Node: License49209  End Tag Table From 57b3eeba49745579e0908a4a2fb54f64b2fad88c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 01:13:03 -0600 Subject: [PATCH 261/560] Merge: org-ql-defpred MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Squashed commit of the following: commit a0ace307b0de3f5e811f042fd9f0b821a0bbc95c Author: Adam Porter Date: Mon Nov 23 01:11:07 2020 -0600 Docs: Fix TOC commit bef9f3c9b5b762070445c76ac3c833e51dd893ba Author: Adam Porter Date: Mon Nov 23 01:09:33 2020 -0600 Docs: (README.org) Add org-ql-defpred commit ff0257696fe87764e3289e12ddc336377a9a5d01 Author: Adam Porter Date: Mon Nov 23 00:52:06 2020 -0600 Docs: Improve defpred.org Thanks to piyo in #emacsconf@freenode. commit 18d6d73a99c336cd637c99309ee5d150106b73b7 Author: Adam Porter Date: Mon Nov 23 00:35:24 2020 -0600 Docs: Improve custom predicate tutorial Closes #155. Thanks to Merlin Göttlinger (@mgttlinger) for suggesting improvements. commit b8cbe36fb3bec23dad5fac07cd11018d98a0e9c1 Author: Adam Porter Date: Mon Nov 23 00:05:52 2020 -0600 Docs: Add custom predicate tutorial commit b1008d0c526b988e958809997351f347af41a7f7 Author: Adam Porter Date: Sun Nov 22 19:34:16 2020 -0600 Docs: Update readme commit 73d4f95cd4eb429774c16b6d403285e9755a2412 Merge: 9a2719f 148a193 Author: Adam Porter Date: Sun Nov 22 19:29:15 2020 -0600 Merge branch 'wip/0.6-pre' into wip/define-predicate ... --- README.org | 64 +- examples.org | 5 + examples/defpred.org | 331 ++++++++++ helm-org-ql.el | 4 +- org-ql-search.el | 4 +- org-ql-view.el | 2 +- org-ql.el | 1499 +++++++++++++++++++++++------------------- org-ql.info | 192 ++++-- tests/test-org-ql.el | 122 ++-- 9 files changed, 1432 insertions(+), 791 deletions(-) create mode 100644 examples/defpred.org diff --git a/README.org b/README.org index b4f8596..5f9e718 100644 --- a/README.org +++ b/README.org @@ -258,15 +258,19 @@ The following predicates, in addition to the keyword arguments, can also take a ** Functions / Macros :PROPERTIES: -:TOC: ignore-children +:TOC: :include descendants +:END: +:CONTENTS: +- [[#agenda-like-views][Agenda-like views]] + - [[#function-org-ql-block][Function: org-ql-block]] +- [[#listing--acting-on-results][Listing / acting-on results]] + - [[#caching][Caching]] + - [[#function-org-ql-select][Function: org-ql-select]] + - [[#function-org-ql-query][Function: org-ql-query]] + - [[#macro-org-ql][Macro: org-ql]] +- [[#custom-predicates][Custom predicates]] + - [[#macro-org-ql-defpred][Macro: org-ql-defpred]] :END: - -- [[#agenda-like-views][Agenda-like views]] - - [[#function-org-ql-block][Function: org-ql-block]] -- [[#listing--acting-on-results][Listing / acting-on results]] - - [[#function-org-ql-select][Function: org-ql-select]] - - [[#function-org-ql-query][Function: org-ql-query]] - - [[#macro-org-ql][Macro: org-ql]] *** Agenda-like views @@ -405,6 +409,44 @@ Examples: Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted. +*** Custom predicates + ++ See: [[file:examples/defpred.org][Custom predicate tutorial]] + +**** Macro: =org-ql-defpred= + +/Arguments:/ ~(name args docstring &key body preambles normalizers)~ + +Define an ~org-ql~ selector predicate named ~org-ql--predicate-NAME~. ~NAME~ may be a symbol or a list of symbols: if a list, the first is used as ~NAME~ and the rest are aliases. ~A~ function is only created for ~NAME~, not for aliases, so a normalizer should be used to replace aliases with ~NAME~ in queries (keep reading). + +~ARGS~ is a ~cl-defun~-style argument list. ~DOCSTRING~ is the function's docstring. + +~BODY~ is the body of the predicate. It will be evaluated with point on the beginning of an Org heading and should return non-nil if the heading's entry is a match. + +~PREAMBLES~ and ~NORMALIZERS~ are lists of ~pcase~ forms matched against Org ~QL~ query sexps. They are spliced into ~pcase~ forms in the definitions of the functions ~org-ql--query-preamble~ and ~org-ql--normalize-query~, which see. Those functions are redefined when this macro is expanded, unless variable ~org-ql-defpred-defer~ is non-nil, in which case those functions should be redefined manually after defining predicates by calling ~org-ql--define-query-preamble-fn~ and ~org-ql--define-normalize-query-fn~. + +~NORMALIZERS~ are used to normalize query expressions to standard forms. For example, when the predicate has aliases, the aliases should be replaced with predicate names using a normalizer. Also, predicate arguments may be put into a more optimal form so that the predicate has less work to do at query time. + +~PREAMBLES~ refer to regular expressions which may be used to search through a buffer directly to a potential match rather than testing the predicate body on each heading. (Naming things is hard.) In each ~pcase~ form in ~PREAMBLES~, the ~pcase~ expression (not the pattern) should be a plist with the following keys, each value of which should be an expression which may refer to variables bound in the pattern: + +~:regexp~ Regular expression which searches directly to a potential match. + +~:case-fold~ Bound to ~case-fold-search~ around the regexp search. + +~:query~ Expression which should replace the query expression, or ~query~ if it should not be changed (e.g. if the regexp is insufficient to determine whether a heading matches, in which case the predicate's body needs to be tested on the heading). If the regexp guarantees a match, this may be simply ~t~, leaving the query expression with no work to do, which improves performance. + +For convenience, within the ~pcase~ patterns, the symbol ~predicate-names~ is a special form which is replaced with a pattern matching any of the predicate's name and aliases. For example, if ~NAME~ were: + +~(heading h)~ + +Then if ~NORMALIZERS~ were: + +~((`(,predicate-names . ,args) `(heading ,@args)))~ + +It would be expanded to: + +~((`(,(or 'heading 'h) . ,args) `(heading ,@args)))~ + ** Dynamic block Org QL provides a dynamic block that lists entries in the current document matching a query. In the header, these parameters are supported: @@ -463,7 +505,11 @@ Simple links may also be written manually in either sexp or non-sexp form, like: ** 0.6-pre -Nothing new yet. +*Added* ++ Macro =org-ql-defpred=, used to define search predicates. (See [[file:examples/defpred.org][tutorial]].) + +*Internal* ++ Predicates are now defined more cleanly with a macro (=org-ql-defpred=) that consolidates functionality related to each predicate. This will also allow users to more easily define custom predicates. ** 0.5 diff --git a/examples.org b/examples.org index eb14f08..7d5f28d 100644 --- a/examples.org +++ b/examples.org @@ -5,6 +5,7 @@ :TOC: :include siblings :ignore this :END: :CONTENTS: +- [[#custom-predicates][Custom predicates]] - [[#agenda-like-view][Agenda-like view]] - [[#entries-from-the-past-week][Entries from the past week]] - [[#find-entries-matching-a-certain-custom_id][Find entries matching a certain CUSTOM_ID]] @@ -18,6 +19,10 @@ - [[#task-list-for-files-in-subdirectories][Task list for files in subdirectories]] :END: +* Custom predicates + ++ [[file:examples/defpred.org][Custom predicate tutorial]] + * Agenda-like view Show an agenda-like view, similar to a "traditional" Org Agenda with Log Mode turned on. diff --git a/examples/defpred.org b/examples/defpred.org new file mode 100644 index 0000000..86565cf --- /dev/null +++ b/examples/defpred.org @@ -0,0 +1,331 @@ +#+TITLE: Org QL Custom Predicates Tutorial +#+OPTIONS: author:nil creator:nil created:nil date:nil num:nil title:t + +[2020-11-22 Sun 22:35] Imagine you have weekly meetings with other people, and during the week you take notes about items to discuss at each meeting. When the time for a meeting comes, you want to quickly and easily search for all of the items to discuss at the meeting. + +You've been experimenting with different ways to track such data in Org. You've tried using tags, but some of the names in question conflict with other tags in your data (e.g. someone's named Charles, but you also work with a firm named Charles, Inc., and you'd prefer to continue using the tag =Charles= for entries about that firm), so you've been using tags like ~:personNAME:~, which seems awkward. You've tried using a ~:person: NAME~ property on entries, which has the advantage of not cluttering the tags list, but also the disadvantage of not being readily visible in an outline. + +So you haven't decided on a long-term solution, but the meetings aren't going to wait--you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged ~:personAlice:~) when you're meeting with her, and all of the entries about Bob (which have the property ~:person: Bob~) when you're meeting with him What do you do? + +* Contents +:PROPERTIES: +:TOC: :include siblings :ignore this +:END: +:CONTENTS: +- [[#using-built-in-predicates][Using built-in predicates]] +- [[#a-custom-person-predicate][A custom (person) predicate]] +- [[#searching-for-multiple-people-at-once][Searching for multiple people at once]] +- [[#normalizing-queries-to-rewrite-arguments][Normalizing queries to rewrite arguments]] +- [[#non-sexp-query-syntax][Non-sexp query syntax]] +- [[#using-multiple-predicates][Using multiple predicates]] +- [[#predicate-aliases][Predicate aliases]] +- [[#appendix-anaphoric-macros][Appendix: Anaphoric macros]] +:END: + +* Using built-in predicates + +You could start by using built-in Org QL predicates to search your data. For example: + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(or (tags "personAlice") + (property "person" "Bob"))) +#+END_SRC + +#+RESULTS[91a413cda23cb65d6bb99212e111f283e5a5c910]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +That was easy enough, but it's not very...semantic. You have to think about the implementation details: Alice uses tags, Bob uses properties, and what if Charlie uses both? It starts to feel complicated, and it's a lot to type out every time. Is there an easier way? + +* A custom ~(person)~ predicate + +Enter =org-ql= custom search predicates. Let's start simple, by defining a predicate to search for just the ~:person:~ property, one person at a time. The predicate will take one argument, a person's name, and search for that property. It would look like this: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred person (name) + "Search for entries with the \"person\" property being NAME." + :body (property "person" name)) +#+END_SRC + +Now let's see what results we get for searching this file for entries about Bob: + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Bob")) +#+END_SRC + +#+RESULTS[c11a4ce2c4f179d7487c9b46eff9f72766bc2bc4]: +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +Hmm, looks like we need to remind Bob to wash his mug and take some mints after lunch. Now what do we need to discuss with Alice? + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice")) +#+END_SRC + +#+RESULTS[1f12f437042bbc077a4696d707805c1367f2ca3d]: +#+BEGIN_EXAMPLE + +#+END_EXAMPLE + +Nothing? Oh, right, Alice's entries use the ~:personAlice:~ tag, so we'll also need to also search those kind of entries. Let's make the predicate do that too: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred person (name) + "Search for entries with the \"person\" property being NAME or having the tag \"personNAME\"." + :body (or (property "person" name) + (tags (concat "person" name)))) +#+END_SRC + +How about now? + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice")) +#+END_SRC + +#+RESULTS[1f12f437042bbc077a4696d707805c1367f2ca3d]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink + +Hmm, I thought we already told her to leave Polly at home. + +* Searching for multiple people at once + +Oh, wait, this week is shortened due to holidays, so we're having a combined meeting. How do we search for entries about either of them? Well, this is the obvious solution: + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(or (person "Alice") + (person "Bob"))) +#+END_SRC + +#+RESULTS[4e4c75bde4fbceaadb076a53410c1625d1283e06]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +And that works fine. But it seems like a lot to type. Could we make the =person= predicate accept multiple names instead? + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred person (&rest names) + "Search for entries about any of NAMES." + :body (cl-loop for name in names + thereis (or (property "person" name) + (tags (concat "person" name))))) +#+END_SRC + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice" "Bob")) +#+END_SRC + +#+RESULTS[4f5971c56616f01d8d3c28a66ef380495ee3e158]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +That was easy! + +* Normalizing queries to rewrite arguments + +Now, all this is well and good if you don't have hundreds of thousands of Org entries in your files. But what if you do? All that =concat='ing happening on every entry could add up, and the query might take a few seconds. What if we could do that stringing-along just once, before running the query? We want to turn our ~(person "Alice" "Bob")~ query into this, with the =:personNAME:= strings already made and the per-person ~(property ...)~ predicates also included: + +#+BEGIN_SRC elisp + (or (tags "personAlice" "personBob") + (property "person" "Alice") + (property "person" "Bob")) +#+END_SRC + +Can we do that? In fact, we can, by using a query normalizer. Normalizers are =pcase= forms (I /know/) that normalize query expressions before execution. We can use one to rewrite the query ahead of time, like this: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred person (&rest names) + "Search for entries about any of NAMES." + :normalizers ((`(person . ,names) + `(or (tags ,@(cl-loop for name in names + collect (concat "person" name))) + ,@(cl-loop for name in names + collect `(property "person" ,name))))) + :body (cl-loop for name in names + thereis (or (property "person" name) + (tags (concat "person" name))))) +#+END_SRC + +Now, don't faint from all the backquoting and unquoting--it's just Lisp, nothing to be afraid of! Let's slow down a moment and see what the normalized query looks like to be sure we're doing it correctly: + +#+BEGIN_SRC elisp :results code :exports both :cache yes + (org-ql--normalize-query '(person "Alice" "Bob")) +#+END_SRC + +#+RESULTS[ebc46fff31b72359353dda539a26c95b7d650df2]: +#+BEGIN_SRC elisp + (or (tags "personAlice" "personBob") + (property "person" "Alice") + (property "person" "Bob")) +#+END_SRC + +And, as they say, Bob's your uncle! Or even if he isn't, let's see if it works: + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice" "Bob")) +#+END_SRC + +#+RESULTS[4f5971c56616f01d8d3c28a66ef380495ee3e158]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +Yep, same result as the non-normalized query. And look at how much simpler it is to write ~(person "Alice" "Bob")~ than to write ~(or (tags "personAlice" "personBob") (property "person" "Alice") (property "person" "Bob"))~. + +* Non-sexp query syntax + +But wait, that's not all! If you order now, we'll throw in non-sexp query syntax for free! That's right, your search could be as simple as typing ~person:Alice,Bob~! + +#+BEGIN_SRC elisp :results none :exports code + (org-ql-search (current-buffer) "person:Alice,Bob") +#+END_SRC + +Don't believe me? Well, you see, queries in this syntax are automatically converted to the sexp syntax, like: + +#+BEGIN_SRC elisp :results code :exports both :cache yes + (org-ql--query-string-to-sexp "person:Alice,Bob") +#+END_SRC + +#+RESULTS[a60655544956644605c23c152570185c329faa87]: +#+BEGIN_SRC elisp + (person "Alice" "Bob") +#+END_SRC + +But that happens automatically when you use a search command like =org-ql-search=. If you have =org-ql= installed already, you could even click this link: [[org-ql-search:person:Alice,Bob][Alice or Bob]]. Which, in Org syntax, looks like: + +#+BEGIN_SRC org + [[org-ql-search:person:Alice,Bob]] +#+END_SRC + +And that would open an Agenda Mode buffer that looks like this: + +#+BEGIN_EXAMPLE + Query: (person "Alice" "Bob") In:meetings.org + [#A] Loud pet parakeet :personAlice: + [#C] Missing sticky notes :personAlice: + [#C] Dirty dishes in sink :personAlice: + [#A] Stinky coffee breath +#+END_EXAMPLE + +* Using multiple predicates + +Oops, you forgot that there's a birthday party in 20 minutes, so you only have time to talk about the highest priority items at this joint meeting today. + +No problem, let's just select high-priority items: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-search (current-buffer) "person:Alice,Bob priority:A") +#+END_SRC + +#+BEGIN_EXAMPLE + Query: (and (person "Alice" "Bob") (priority "A")) In:meetings.org + [#A] Loud pet parakeet :personAlice: + [#A] Stinky coffee breath +#+END_EXAMPLE + +* Predicate aliases + +And, you know what, if you're just so busy that you don't even have time to type the word =person=, you can add an abbreviated alias, =p=, like this: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred (person p) (&rest names) + "Search for entries about any of NAMES." + :normalizers ((`(,predicate-names . ,names) + `(or (tags ,@(cl-loop for name in names + collect (concat "person" name))) + ,@(cl-loop for name in names + collect `(property "person" ,name))))) + :body (cl-loop for name in names + thereis (or (property "person" name) + (tags (concat "person" name))))) +#+END_SRC + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-search (current-buffer) "p:Alice,Bob priority:A") +#+END_SRC + +#+BEGIN_EXAMPLE + Query: (and (person "Alice" "Bob") (priority "A")) In:meetings.org + [#A] Loud pet parakeet :personAlice: + [#A] Stinky coffee breath +#+END_EXAMPLE + +(It's up to you to remember whether =p= means =person= or =priority=, but code can't solve everything.) + +* Appendix: Anaphoric macros + +Finally, if you're a Lisper who appreciates anaphora, you might prefer a more syntactically concise definition of the predicate using Dash macros: + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred (person p) (&rest names) + "Search for entries about any of NAMES." + :normalizers ((`(,predicate-names . ,names) + `(or (tags ,@(--map `(concat "person" ,it) names)) + ,@(--map `(property "person" ,it) names)))) + :body (--any (or (property "person" name) + (tags (concat "person" name))) + names)) +#+END_SRC + +Let's make sure it works: + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice" "Bob")) +#+END_SRC + +#+RESULTS[4f5971c56616f01d8d3c28a66ef380495ee3e158]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +Have fun making custom search predicates! + +* Example data +:PROPERTIES: +:TOC: :ignore (this descendants) +:END: + +** [#A] Loud pet parakeet :personAlice: + +** [#C] Missing sticky notes :personAlice: +:PROPERTIES: +:person: Bob +:END: + +** [#C] Dirty dishes in sink :personAlice: +:PROPERTIES: +:person: Bob +:END: + +** [#A] Stinky coffee breath +:PROPERTIES: +:person: Bob +:END: + diff --git a/helm-org-ql.el b/helm-org-ql.el index e95bc5f..e75cf7b 100644 --- a/helm-org-ql.el +++ b/helm-org-ql.el @@ -173,7 +173,7 @@ Is transformed into this query: (interactive) (let ((buffers-files (with-current-buffer (helm-buffer-get) helm-org-ql-buffers-files)) - (query (org-ql--plain-query helm-pattern))) + (query (org-ql--query-string-to-sexp helm-pattern))) (helm-run-after-exit #'org-ql-search buffers-files query))) ;;;###autoload @@ -189,7 +189,7 @@ Is transformed into this query: ;; Expansion of `helm-build-sync-source' macro. (helm-make-source name 'helm-source-sync :candidates (lambda () - (let* ((query (org-ql--plain-query helm-pattern)) + (let* ((query (org-ql--query-string-to-sexp helm-pattern)) (window-width (window-width (helm-window)))) (when query (with-current-buffer (helm-buffer-get) diff --git a/org-ql-search.el b/org-ql-search.el index 70d846d..c60bd8e 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -158,7 +158,7 @@ necessary." ;; Read sexp query. (read query) ;; Parse non-sexp query into sexp query. - (org-ql--plain-query query))) + (org-ql--query-string-to-sexp query))) (list query))) (results (org-ql-select buffers-files query :action 'element-with-markers @@ -273,7 +273,7 @@ For example, an org-ql dynamic block header could look like: #+BEGIN: org-ql :query (todo \"UNDERWAY\") :columns (priority todo heading) :sort (priority date) :ts-format \"%Y-%m-%d %H:%M\"" (-let* (((&plist :query :columns :sort :ts-format :take) params) (query (cl-etypecase query - (string (org-ql--plain-query query)) + (string (org-ql--query-string-to-sexp query)) (list ;; SAFETY: Query is in sexp form: ask for confirmation, because it could contain arbitrary code. (org-ql--ask-unsafe-query query) query))) diff --git a/org-ql-view.el b/org-ql-view.el index b954fc0..959484c 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -775,7 +775,7 @@ When opened, the link searches the buffer it's opened from." ;; Read sexp query. (read query) ;; Parse non-sexp query into sexp query. - (org-ql--plain-query query))))) + (org-ql--query-string-to-sexp query))))) (define-infix-command org-ql-view--transient-in () :description (lambda () (org-ql-view--format-transient-lisp-argument "In buffers/files" org-ql-view-buffers-files)) diff --git a/org-ql.el b/org-ql.el index bd53108..b4b98b3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -125,7 +125,9 @@ the value returned by it at that node.") (eval-and-compile (defvar org-ql-predicates - (list (list :name 'org-back-to-heading :fn (symbol-function 'org-back-to-heading))) + ;; FIXME: Is this remapping still necessary? It was mapping `org-back-to-heading' + ;; to itself until now, so maybe I broke it and it doesn't matter anymore. + (list (cons 'org-back-to-heading (list :name 'org-back-to-heading :fn (symbol-function 'outline-back-to-heading)))) "Plist of predicates, their corresponding functions, and their docstrings. This list should not contain any duplicates.")) @@ -254,7 +256,7 @@ returns nil or non-nil." (user-error "Can't open file: %s" it))))) ;; Ignore special/hidden buffers. (--remove (string-prefix-p " " (buffer-name it))))) - (query (org-ql--pre-process-query query)) + (query (org-ql--normalize-query query)) ((&plist :query :preamble :preamble-case-fold) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) (action (pcase action @@ -377,13 +379,15 @@ If NARROW is non-nil, buffer will not be widened." (let (orig-fns) (--each org-ql-predicates ;; Save original function mappings. - (let ((name (plist-get it :name))) + (let* ((it (cdr it)) + (name (plist-get it :name))) (push (list :name name :fn (symbol-function name)) orig-fns))) (unwind-protect (progn (--each org-ql-predicates ;; Set predicate functions. - (fset (plist-get it :name) (plist-get it :fn))) + (let ((it (cdr it))) + (fset (plist-get it :name) (plist-get it :fn)))) ;; Run query. (save-excursion (save-restriction @@ -586,356 +590,6 @@ Or, when possible, fix the problem." (org-ql--sanity-check-form (cdr elem))) else do (check elem)))) -(defun org-ql--pre-process-query (query) - "Return QUERY having been pre-processed. -Replaces bare strings with (regexp) selectors, and appropriate -`ts'-related selectors." - ;; This is unsophisticated, but it works. - ;; TODO: Maybe query pre-processing should be done in one place, - ;; rather than here and in --query-predicate. - ;; NOTE: Don't be scared by the `pcase' patterns! They make this - ;; all very easy once you grok the backquoting and unquoting. - (cl-labels ((rec (element) - (pcase element - (`(or . ,clauses) `(or ,@(mapcar #'rec clauses))) - (`(and . ,clauses) `(and ,@(mapcar #'rec clauses))) - (`(not . ,clauses) `(not ,@(mapcar #'rec clauses))) - (`(when ,condition . ,clauses) `(when ,(rec condition) - ,@(mapcar #'rec clauses))) - (`(unless ,condition . ,clauses) `(unless ,(rec condition) - ,@(mapcar #'rec clauses))) - ;; TODO: Combine (regexp) when appropriate (i.e. inside an OR, not an AND). - ((pred stringp) `(regexp ,element)) - ;; Quote children queries so the user doesn't have to. - (`(children ,query) `(children ',query)) - (`(children) '(children (lambda () t))) - (`(descendants ,query) `(descendants ',query)) - (`(descendants) '(descendants (lambda () t))) - (`(parent ,query) `(parent ,(org-ql--query-predicate (rec query)))) - (`(parent) '(parent (lambda () t))) - (`(ancestors ,query) `(ancestors ,(org-ql--query-predicate (rec query)))) - (`(ancestors) '(ancestors (lambda () t))) - ;; Timestamp-based predicates. I think this is the way that makes the most sense: - ;; set the limit to N days in the future, adjusted to 23:59:59 (since Org doesn't - ;; support timestamps down to the second, anyway, there should be no need to adjust - ;; it forward to 00:00:00 of the next day). That way, e.g. if it's Monday at 3 PM, - ;; and N is 1, rather than showing items up to 3 PM Tuesday, it will show items any - ;; time on Tuesday. If this isn't desired, the user can pass a specific timestamp. - (`(,(and pred (or 'clocked 'closed)) - ,(and num-days (pred numberp))) - ;; (clocked) and (closed) implicitly look into the past. - (let ((from (->> (ts-now) - (ts-adjust 'day (* -1 num-days)) - (ts-apply :hour 0 :minute 0 :second 0)))) - `(,pred :from ,from))) - (`(deadline auto) - ;; Use `org-deadline-warning-days' as the :to arg. - (let ((to (->> (ts-now) - (ts-adjust 'day org-deadline-warning-days) - (ts-apply :hour 23 :minute 59 :second 59)))) - `(deadline-warning :to ,to))) - (`(,(and pred (or 'deadline 'scheduled 'planning)) - ,(and num-days (pred numberp))) - (let ((to (->> (ts-now) - (ts-adjust 'day num-days) - (ts-apply :hour 23 :minute 59 :second 59)))) - `(,pred :to ,to))) - - ;; Headings. - (`(h . ,args) - ;; "h" alias. - `(heading ,@args)) - - ;; Outline level. - (`(level . ,args) - ;; Arguments could be given as strings (e.g. from a non-Lisp query). - `(level ,@(--map (pcase it - ((or "<" "<=" ">" ">=" "=") - (intern it)) - ((pred stringp) (string-to-number it)) - (_ it)) - args))) - - ;; Regexps. - (`(r . ,args) - ;; "r" alias. - `(regexp ,@args)) - - ;; Outline paths. - (`(,(or 'outline-path 'olp) . ,strings) - ;; Regexp quote headings. - `(outline-path ,@(mapcar #'regexp-quote strings))) - (`(,(or 'outline-path-segment 'olps) . ,strings) - ;; Regexp quote headings. - `(outline-path-segment ,@(mapcar #'regexp-quote strings))) - - ;; Priorities - (`(priority ,(and (or '= '< '> '<= '>=) comparator) ,letter) - ;; Quote comparator. - `(priority ',comparator ,letter)) - - ;; Properties. - (`(property ,property . ,value) - ;; Convert keyword property arguments to strings. Non-sexp - ;; queries result in keyword property arguments (because to do - ;; otherwise would require ugly special-casing in the parsing). - (when (keywordp property) - (setf property (substring (symbol-name property) 1))) - (cons 'property (cons property value))) - - ;; Source blocks. - (`(src . ,args) - ;; Rewrite to use keyword args. - (-let (regexps lang keyword-index) - (cond ((plist-get args :lang) - ;; Lang given first, or only lang given. - (setf lang (plist-get args :lang) - regexps (seq-difference args (list :lang lang)))) - ((setf keyword-index (-find-index #'keywordp args)) - ;; Regexps and lang given. - (setf lang (plist-get (cl-subseq args keyword-index) :lang) - regexps (cl-subseq args 0 keyword-index))) - (t ;; Only regexps given. - (setf regexps args))) - (when regexps - ;; This feels awkward and wrong, but we have to quote lists - ;; and avoid quoting nil. There must be a better way. - (setf regexps `(',regexps))) - `(src :lang ,lang :regexps ,@regexps))) - - ;; Tags. - (`(,(or 'tags-all 'tags&) . ,tags) `(and ,@(--map `(tags ,it) tags))) - ;; MAYBE: -all versions for inherited and local. - ;; Inherited and local predicate aliases. - (`(,(or 'tags-i 'itags 'inherited-tags) . ,tags) `(tags-inherited ,@tags)) - (`(,(or 'tags-l 'ltags 'local-tags) . ,tags) `(tags-local ,@tags)) - (`(,(or 'tags*) . ,regexps) `(tags-regexp ,@regexps)) - - ;; Timestamps - (`(,(or 'ts-active 'ts-a) . ,rest) `(ts :type active ,@rest)) - (`(,(or 'ts-inactive 'ts-i) . ,rest) `(ts :type inactive ,@rest)) - ;; Any other form: passed through unchanged. - (_ element)))) - (rec query))) - -(defun org-ql--query-preamble (query) - "Return plist (QUERY PREAMBLE PREAMBLE-CASE-FOLD) for QUERY. -When QUERY has a clause with a corresponding preamble, and it's -appropriate to use one (i.e. the clause is not in an `or'), -replace the clause with a preamble." - (pcase org-ql-use-preamble - ('nil (list :query query :preamble nil)) - (_ (let ((preamble-case-fold t) - org-ql-preamble) - (cl-labels ((rec (element) - (or (when org-ql-preamble - ;; Only one preamble is allowed - element) - (pcase element - (`(or _) element) - (`(clocked . ,_) - (setq org-ql-preamble org-ql-clock-regexp) - element) - (`(closed . ,_) - (setq org-ql-preamble org-closed-time-regexp) - ;; Return element, because the predicate still needs testing. - element) - (`(deadline . ,_) - (setq org-ql-preamble org-deadline-time-regexp) - ;; Return element, because the predicate still needs testing. - element) - (`(regexp . ,regexps) - ;; Search for first regexp, then confirm with predicate. - (setq org-ql-preamble (car regexps)) - element) - (`(todo . ,(and todo-keywords (guard todo-keywords))) - (setf org-ql-preamble - (rx-to-string `(seq bol (1+ "*") (1+ space) (or ,@todo-keywords) (or " " eol)) - t) - preamble-case-fold nil) - ;; Return nil, don't test the predicate. - nil) - (`(habit) - (setq org-ql-preamble (rx bol (0+ space) ":STYLE:" (1+ space) "habit" (0+ space) eol)) - nil) - - ;; Heading text. - ;; MAYBE: Adjust regexp to avoid matching in tag list. - (`(heading ,regexp) - ;; Only one regexp: match with preamble, then let predicate confirm (because - ;; the match could be in e.g. the tags rather than the heading text). - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) - ,regexp) - 'no-group)) - element) - (`(heading . ,regexps) - ;; Multiple regexps: use preamble to match against first - ;; regexp, then let the predicate match the rest. - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) - ,(car regexps)) - 'no-group)) - element) - - ;; Heading levels. - (`(level ,comparator-or-num ,num) - (let ((repeat (pcase comparator-or-num - ('< `(repeat 1 ,(1- num) "*")) - ('<= `(repeat 1 ,num "*")) - ('> `(>= ,(1+ num) "*")) - ('>= `(>= ,num "*")) - ((pred integerp) `(repeat ,comparator-or-num ,num "*"))))) - (setq org-ql-preamble (rx-to-string `(seq bol ,repeat " ") t)) - ;; Return nil, because we don't need to test the predicate. - nil)) - (`(level ,num) - (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) - nil) - - ;; Links. Always return nil, because we - ;; shouldn't need to test the predicate. - (`(link) - (setq org-ql-preamble - ;; Match a link with a target and optionally a description. - (rx (or bol (1+ blank)) - "[[" (1+ (not (any "]"))) "]" - (optional (seq "[" (0+ (not (any "]"))) "]")) - "]" - (or eol blank))) - nil) - ;; NOTE: I would use the form "(map :regexp-p)", or at least - ;; "(map (:regexp-p regexp))" but they require map versions from - ;; ELPA. That would be fine, except that I can't automatically - ;; install those versions with makem.sh into a sandbox, because - ;; `package-install' doesn't accept a version argument. So I - ;; have to use `plist-get' here for now. Maybe when we drop - ;; support for Emacs <28... - (`(link ,(and description-or-target - (guard (not (keywordp description-or-target))))) - (setq org-ql-preamble - (org-ql--link-regexp :description-or-target - (regexp-quote description-or-target))) - nil) - (`(link . ,plist) - (setq org-ql-preamble - (org-ql--link-regexp - :description - (when (plist-get plist :description) - (regexp-quote (plist-get plist :description))) - :target (when (plist-get plist :target) - (regexp-quote (plist-get plist :target))))) - nil) - - ;; Planning lines. - (`(planning . ,_) - (setq org-ql-preamble org-ql-planning-regexp) - ;; Return element, because the predicate still needs testing. - element) - - ;; Priorities. - ;; NOTE: This only accepts A, B, or C. I haven't seen - ;; other priorities in the wild, so this will do for now. - (`(priority) - ;; Any priority cookie. - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) "[#" (in "ABC") "]") t)) - nil) - (`(priority ,(and (or ''= ''< ''> ''<= ''>=) comparator) ,letter) - ;; Comparator and priority letter. - ;; NOTE: The double-quoted comparators. See below. - (let* ((priority-letters '("A" "B" "C")) - (index (-elem-index letter priority-letters)) - ;; NOTE: Higher priority == lower number. - ;; NOTE: Because we need to support both preamble-based queries and - ;; regular predicate ones, we work around an idiosyncrasy of query - ;; pre-processing by accepting both quoted and double-quoted comparator - ;; function symbols. Not the most elegant solution, but it works. - (priorities (s-join "" (pcase comparator - ((or '= ''=) (list letter)) - ((or '> ''>) (cl-subseq priority-letters 0 index)) - ((or '>= ''>=) (cl-subseq priority-letters 0 (1+ index))) - ((or '< ''<) (cl-subseq priority-letters (1+ index))) - ((or '<= ''<=) (cl-subseq priority-letters index)))))) - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ blank) (optional (1+ upper) (1+ blank)) - "[#" (in ,priorities) "]") t)) - nil)) - (`(priority . ,letters) - ;; One or more priorities. - ;; MAYBE: Disable case-folding. - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ blank) - (optional (1+ upper) (1+ blank)) - "[#" (or ,@letters) "]") t)) - nil) - - ;; Properties. - ;; MAYBE: Should case folding be disabled for properties? What about values? - (`(property ,property ,value) - ;; We do NOT return nil, because the predicate still needs to be tested, - ;; because the regexp could match a string not inside a property drawer. - (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":" ,property ":" - (1+ space) ,value (0+ space) eol))) - element) - (`(property ,property) - ;; We do NOT return nil, because the predicate still needs to be tested, - ;; because the regexp could match a string not inside a property drawer. - ;; NOTE: The preamble only matches if there appears to be a value. - ;; A line like ":ID: " without any other text does not match. - (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":" ,property ":" (1+ space) - (minimal-match (1+ not-newline)) eol))) - element) - ;; MAYBE: Support (property) without args. - ;; (`(property) - ;; ;; We do NOT return nil, because the predicate still needs to be tested, - ;; ;; because the regexp could match a string not inside a property drawer. - ;; ;; NOTE: The preamble only matches if there appears to be a value. - ;; ;; A line like ":ID: " without any other text does not match. - ;; (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":" (1+ (not (or space ":"))) ":" - ;; (1+ space) (minimal-match (1+ not-newline)) eol))) - ;; element) - - ;; Src blocks. - (`(src . ,args) - (setq org-ql-preamble (org-ql--format-src-block-regexp (plist-get args :lang))) - ;; Always check contents with predicate. - element) - - ;; Scheduled. - (`(scheduled . ,_) - (setq org-ql-preamble org-scheduled-time-regexp) - ;; Return element, because the predicate still needs testing. - element) - - ;; Tags. - (`((or 'tags-local 'local-tags 'tags-l 'ltags) . ,tags) - ;; When searching for local, non-inherited tags, we can - ;; search directly to headings containing one of the tags. - (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ space) (1+ not-newline) - ":" (or ,@tags) ":") - t)) - ;; Return nil, because we don't need to test the predicate. - nil) - - ;; Timestamps. - (`(ts . ,rest) - (setq org-ql-preamble (pcase (plist-get rest :type) - ((or 'nil 'both) org-tsr-regexp-both) - ('active org-tsr-regexp) - ('inactive org-ql-tsr-regexp-inactive))) - ;; Predicate needs testing only when args are present. - (-let (((&keys :from :to :on) rest)) - (when (or from to on) - element))) - (`(and . ,rest) - (let ((clauses (mapcar #'rec rest))) - `(and ,@(-non-nil clauses)))) - (_ element))))) - (setq query (pcase (mapcar #'rec (list query)) - ((or `(nil) - `((nil)) - `((and)) - `((or))) - t) - (query (-flatten-n 1 query)))) - (list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold)))))) - (cl-defun org-ql--link-regexp (&key description-or-target description target) "Return a regexp matching Org links according to arguments. Each argument is treated as a regexp (so non-regexp strings @@ -1000,6 +654,351 @@ respectively." "#+end_src") t)) +(defun org-ql--byte-compile-warning (_string _pos _fill level) + "Signal an `org-ql-invalid-query' error. +Arguments STRING, POS, FILL, and LEVEL are according to +`byte-compile-log-warning-function'." + ;; Used as the `byte-compile-log-warning-function' in `org-ql--query-preamble'. + (signal 'org-ql-invalid-query level)) + +(defun org-ql--query-predicate (query) + "Return predicate function for QUERY." + ;; Use custom log function to prevent warnings for e.g. partially typed queries. + (let ((byte-compile-log-warning-function #'org-ql--byte-compile-warning)) + (byte-compile + `(lambda () + (cl-macrolet ((clocked (&key from to on) + (org-ql--from-to-on) + `(org-ql--predicate-clocked :from ,from :to ,to)) + (closed (&key from to on) + (org-ql--from-to-on) + `(org-ql--predicate-closed :from ,from :to ,to)) + (deadline (&key from to on) + (org-ql--from-to-on) + `(org-ql--predicate-deadline :from ,from :to ,to)) + (planning (&key from to on) + (org-ql--from-to-on) + `(org-ql--predicate-planning :from ,from :to ,to)) + (scheduled (&key from to on) + (org-ql--from-to-on) + `(org-ql--predicate-scheduled :from ,from :to ,to)) + (ts (&key from to on (type 'both)) + (org-ql--from-to-on) + `(org-ql--predicate-ts :from ,from :to ,to + :regexp ,(pcase type + ('both org-tsr-regexp-both) + ('active org-tsr-regexp) + ('inactive org-ql-tsr-regexp-inactive))))) + ,query))))) + +;;;;; String query parsing + +;; This section implements parsing of "plain," non-Lisp queries using the `peg' +;; library. NOTE: This needs to appear after the predicates are defined. + +(require 'peg) + +;; Fix compiler warnings probably caused by `peg' not using lexical-binding. +;; TODO: File bug report upstream. +(defvar peg-errors nil) +(defvar peg-stack nil) + +(defmacro org-ql--peg-parse-string (rules string &optional noerror) + "Parse STRING according to RULES." + ;; This sentence was in the docstring but Checkdoc is complaining, + ;; so moving it to a comment: "If NOERROR is non-nil, push nil + ;; resp. t if the parse failed resp. succeded instead of signaling + ;; an error." + + ;; Unfortunately, this macro was moved to peg-tests.el, so we copy it here. + `(with-temp-buffer + (insert ,string) + (goto-char (point-min)) + ,(if noerror + (let ((entry (make-symbol "entry")) + (start (caar rules))) + `(peg-parse (,entry (or (and ,start `(-- t)) "")) + . ,rules)) + `(peg-parse . ,rules)))) + +(cl-eval-when (compile load eval) + ;; This `eval-when' is necessary, otherwise the macro does not define + ;; the function correctly, apparently because `org-ql-predicates' + ;; ends up being not defined correctly at expansion time. + + (defun org-ql--def-query-string-to-sexp-fn (predicates) + "Define function `org-ql--query-string-to-sexp' according to PREDICATES. +Builds the PEG expression using PREDICATES (which should be the +value of `org-ql-predicates')." + (let* ((names (--map (symbol-name (plist-get (cdr it) :name)) + predicates)) + (aliases (->> predicates + (--map (plist-get (cdr it) :aliases)) + -non-nil + -flatten + (-map #'symbol-name))) + (predicates (->> (append names aliases) + -uniq + ;; Sort the keywords longest-first to work around what seems to be an + ;; obscure bug in `peg': when one keyword is a substring of another, + ;; and the shorter one is listed first, the shorter one fails to match. + (-sort (-on #'> #'length))))) + (fset 'org-ql--query-string-to-sexp + (byte-compile + `(cl-function + (lambda (input &optional (boolean 'and)) + "Return query parsed from plain query string INPUT. +Multiple predicates are combined with BOOLEAN." + (unless (s-blank-str? input) + (let* ((query (org-ql--peg-parse-string + ((query (+ term + (opt (+ (syntax-class whitespace) (any))))) + (term (or (and negation (list positive-term) + ;; This is a bit confusing, but it seems to work. There's probably a better way. + `(pred -- (list 'not (car pred)))) + positive-term)) + (positive-term (or (and predicate-with-args `(pred args -- (cons (intern pred) args))) + (and predicate-without-args `(pred -- (list (intern pred)))) + (and plain-string `(s -- (list 'regexp s))))) + (plain-string (or quoted-arg unquoted-arg)) + (predicate-with-args (substring predicate) ":" args) + (predicate-without-args (substring predicate) ":") + (predicate (or ,@predicates)) + (args (list (+ (and (or keyword-arg quoted-arg unquoted-arg) (opt separator))))) + (keyword-arg (and keyword "=" `(kw -- (intern (concat ":" kw))))) + (keyword (substring (+ (not (or separator "=" "\"" (syntax-class whitespace))) (any)))) + (quoted-arg "\"" (substring (+ (not (or separator "\"")) (any))) "\"") + (unquoted-arg (substring (+ (not (or separator "\"" (syntax-class whitespace))) (any)))) + (negation "!") + (separator "," )) + input 'noerror))) + ;; Discard the t that `peg-parse-string' always returns as the first + ;; element. I don't know what it means, but we don't want it. + (if (> (length (cdr query)) 1) + (cons boolean (nreverse (cdr query))) + (cadr query))))))))))) + +;;;;; Predicate definition + +(defvar org-ql-defpred-defer nil + "Defer expensive function redefinitions when defining predicates. +When non-nil, defining a predicate with `org-ql-defpred' does not +cause the functions `org-ql--normalize-query', +`org-ql--query-preamble', and `org-ql--query-string-to-sexp' to +be redefined. These functions must be redefined in order to +account for new predicates, but when defining many +predicates (like at load time), that may be deferred for +performance (after which those functions should be updated +manually; see the definition of `org-ql-defpred').") + +;; Yes, these two functions are a little hairy: `pcase' is challenging +;; enough, but splicing forms into one is something else. But it's +;; worth it to do this ugly stuff here, in one place, so the +;; `org-ql-defpred' macro becomes easy to use. + +(defun org-ql--define-normalize-query-fn (predicates) + "Define function `org-ql--normalize-query' for PREDICATES. +PREDICATES should be the value of `org-ql-predicates'." + (let ((normalizer-patterns (->> predicates + (--map (plist-get (cdr it) :normalizers)) + (-flatten-n 1)))) + (fset 'org-ql--normalize-query + (byte-compile + `(lambda (query) + "Return normalized form of QUERY expression. +This function is defined by calling +`org-ql--define-normalize-query-fn', which uses normalizer forms +defined in `org-ql-predicates' by calling `org-ql-defpred'." + (cl-labels ((rec (element) + (pcase element + (`(or . ,clauses) `(or ,@(mapcar #'rec clauses))) + (`(and . ,clauses) `(and ,@(mapcar #'rec clauses))) + (`(not . ,clauses) `(not ,@(mapcar #'rec clauses))) + (`(when ,condition . ,clauses) `(when ,(rec condition) + ,@(mapcar #'rec clauses))) + (`(unless ,condition . ,clauses) `(unless ,(rec condition) + ,@(mapcar #'rec clauses))) + ;; TODO: Combine (regexp) when appropriate (i.e. inside an OR, not an AND). + ((pred stringp) `(regexp ,element)) + + ,@normalizer-patterns + + ;; Any other form: passed through unchanged. + (_ element)))) + (rec query))))))) + +(defun org-ql--define-query-preamble-fn (predicates) + "Define function `org-ql--query-preamble' for PREDICATES. +PREDICATES should be the value of `org-ql-predicates'." + ;; NOTE: I don't how the `list' symbol ends up in the list, but anyway... + (let* ((preamble-patterns + (-flatten-n 1 (-non-nil + ;; NOTE: Using -let instead of pcase-let here because I can't make map 2.1 install in the test sandbox. + (--map (-let* (((&plist :preambles) (cdr it))) + (--map (pcase-let* ((`(,pattern ,exp) it)) + `(,pattern + (-let* (((&plist :regexp :case-fold :query) ,exp)) + (setf org-ql-preamble regexp + preamble-case-fold case-fold) + ;; NOTE: Even when `predicate' is nil, it must be returned in the pcase form. + query))) + preambles)) + predicates))))) + (fset 'org-ql--query-preamble + `(lambda (query) + "Return preamble data plist for QUERY. +The plist has the following keys: + + :preamble Regexp to search the Org buffer for to find potential + matches. If the regexp doesn't guarantee a match to + QUERY, the :query key should be an appropriate query + expression to test against the heading (i.e. usually + QUERY again). + + :preamble-case-fold What to bind variable `case-fold-search' to + around the regexp search. + + :query The query expression to use instead of QUERY (or QUERY + again, when appropriate). + +This function is defined by calling +`org-ql--define-query-preamble-fn', which uses preamble forms +defined in `org-ql-predicates' by calling `org-ql-defpred'." + (pcase org-ql-use-preamble + ('nil (list :query query :preamble nil)) + (_ (let ((preamble-case-fold t) + org-ql-preamble) + (cl-labels ((rec (element) + (or (when org-ql-preamble + ;; Only one preamble is allowed + element) + (pcase element + (`(or _) element) + + ,@preamble-patterns + + (`(and . ,rest) + (let ((clauses (mapcar #'rec rest))) + `(and ,@(-non-nil clauses)))) + (_ element))))) + (setq query (pcase (mapcar #'rec (list query)) + ((or `(nil) + `((nil)) + `((and)) + `((or))) + t) + (`(t) t) + (query (-flatten-n 1 query)))) + (list :query query :preamble org-ql-preamble :preamble-case-fold preamble-case-fold))))))) + ;; For some reason, byte-compiling the backquoted lambda form directly causes a warning + ;; that `query' refers to an unbound variable, even though that's not the case, and the + ;; function still works. But to avoid the warning, we byte-compile it afterward. + (byte-compile 'org-ql--query-preamble))) + +(cl-defmacro org-ql-defpred (name args docstring &key body preambles normalizers) + "Define an `org-ql' selector predicate named `org-ql--predicate-NAME'. +NAME may be a symbol or a list of symbols: if a list, the first +is used as NAME and the rest are aliases. A function is only +created for NAME, not for aliases, so a normalizer should be used +to replace aliases with NAME in queries (keep reading). + +ARGS is a `cl-defun'-style argument list. DOCSTRING is the +function's docstring. + +BODY is the body of the predicate. It will be evaluated with +point on the beginning of an Org heading and should return +non-nil if the heading's entry is a match. + +PREAMBLES and NORMALIZERS are lists of `pcase' forms matched +against Org QL query sexps. They are spliced into `pcase' forms +in the definitions of the functions `org-ql--query-preamble' and +`org-ql--normalize-query', which see. Those functions are +redefined when this macro is expanded, unless variable +`org-ql-defpred-defer' is non-nil, in which case those functions +should be redefined manually after defining predicates by calling +`org-ql--define-query-preamble-fn' and `org-ql--define-normalize-query-fn'. + +NORMALIZERS are used to normalize query expressions to standard +forms. For example, when the predicate has aliases, the aliases +should be replaced with predicate names using a normalizer. +Also, predicate arguments may be put into a more optimal form so +that the predicate has less work to do at query time. + +PREAMBLES refer to regular expressions which may be used to +search through a buffer directly to a potential match rather than +testing the predicate body on each heading. (Naming things is +hard.) In each `pcase' form in PREAMBLES, the `pcase' +expression (not the pattern) should be a plist with the following +keys, each value of which should be an expression which may refer +to variables bound in the pattern: + + :regexp Regular expression which searches directly to a + potential match. + + :case-fold Bound to `case-fold-search' around the regexp search. + + :query Expression which should replace the query expression, + or `query' if it should not be changed (e.g. if the + regexp is insufficient to determine whether a + heading matches, in which case the predicate's body + needs to be tested on the heading). If the regexp + guarantees a match, this may be simply t, leaving the + query expression with no work to do, which improves + performance. + +For convenience, within the `pcase' patterns, the symbol +`predicate-names' is a special form which is replaced with a +pattern matching any of the predicate's name and aliases. For +example, if NAME were: + + (heading h) + +Then if NORMALIZERS were: + + ((`(,predicate-names . ,args) + `(heading ,@args))) + +It would be expanded to: + + ((`(,(or 'heading 'h) . ,args) + `(heading ,@args)))" + ;; NOTE: The debug form works, completely! For example, use `edebug-defun' + ;; on the `heading' predicate, then evaluate this form: + ;; (let* ((query '(heading "HEADING")) + ;; (normalized (org-ql--normalize-query query)) + ;; (preamble (org-ql--query-preamble normalized))) + ;; (list :query query + ;; :normalized normalized + ;; :preamble preamble)) + (declare (debug ([&or symbolp listp] listp stringp + &rest [&or [":body" def-body] + [":normalizers" (&rest (sexp def-body))] + [":preambles" (&rest (sexp def-body))]])) + (indent defun)) + (let* ((aliases (when (listp name) + (cdr name))) + (name (cl-etypecase name + (list (car name)) + (atom name))) + (fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) + (predicate-name (intern (symbol-name name))) + (predicate-names (delq nil (cons predicate-name aliases))) + (normalizers (cl-sublis (list (cons 'predicate-names (cons 'or (--map (list 'quote it) predicate-names)))) + normalizers)) + (preambles (cl-sublis (list (cons 'predicate-names (cons 'or (--map (list 'quote it) predicate-names)))) + preambles))) + `(progn + (cl-eval-when (compile load eval) + (cl-defun ,fn-name ,args ,docstring ,body)) + (setf (map-elt org-ql-predicates ',predicate-name) + `(:name ,',name :aliases ,',aliases :fn ,',fn-name :docstring ,,docstring :args ,',args + :normalizers ,',normalizers :preambles ,',preambles)) + (unless org-ql-defpred-defer + ;; Reversing preserves the order in which predicates were defined. + (org-ql--define-normalize-query-fn (reverse org-ql-predicates)) + (org-ql--define-query-preamble-fn (reverse org-ql-predicates)) + (org-ql--def-query-string-to-sexp-fn (reverse org-ql-predicates)))))) + (defmacro org-ql--from-to-on () "For internal use. Expands into a form that processes arguments to timestamp-related @@ -1043,95 +1042,164 @@ predicates." ((pred stringp) (ts-parse-fill 'end to)) ((pred ts-p) to)))))) -(defun org-ql--byte-compile-warning (_string _pos _fill level) - "Signal an `org-ql-invalid-query' error. -Arguments STRING, POS, FILL, and LEVEL are according to -`byte-compile-log-warning-function'." - ;; Used as the `byte-compile-log-warning-function' in `org-ql--query-preamble'. - (signal 'org-ql-invalid-query level)) +;;;;;; Predicates -(defun org-ql--query-predicate (query) - "Return predicate function for QUERY." - ;; Use custom log function to prevent warnings for e.g. partially typed queries. - (let ((byte-compile-log-warning-function #'org-ql--byte-compile-warning)) - (byte-compile - `(lambda () - (cl-macrolet ((clocked (&key from to on) - (org-ql--from-to-on) - `(org-ql--predicate-clocked :from ,from :to ,to)) - (closed (&key from to on) - (org-ql--from-to-on) - `(org-ql--predicate-closed :from ,from :to ,to)) - (deadline (&key from to on) - (org-ql--from-to-on) - `(org-ql--predicate-deadline :from ,from :to ,to)) - (planning (&key from to on) - (org-ql--from-to-on) - `(org-ql--predicate-planning :from ,from :to ,to)) - (scheduled (&key from to on) - (org-ql--from-to-on) - `(org-ql--predicate-scheduled :from ,from :to ,to)) - (ts (&key from to on (type 'both)) - (org-ql--from-to-on) - `(org-ql--predicate-ts :from ,from :to ,to - :regexp ,(pcase type - ('both org-tsr-regexp-both) - ('active org-tsr-regexp) - ('inactive org-ql-tsr-regexp-inactive))))) - ,query))))) +(cl-eval-when (compile load eval) + ;; Improve load time by deferring the per-predicate preamble- and normalizer-function + ;; redefinitions until all of the predicates have been defined. + (setf org-ql-defpred-defer t)) -;;;;; Predicates - -(org-ql--defpred category (&rest categories) +(org-ql-defpred category (&rest categories) "Return non-nil if current heading is in one or more of CATEGORIES (a list of strings)." - (when-let ((category (org-get-category (point)))) - (cl-typecase categories - (null t) - (otherwise (member category categories))))) + :body (when-let ((category (org-get-category (point)))) + (cl-typecase categories + (null t) + (otherwise (member category categories))))) -(org-ql--defpred path (&rest regexps) - "Return non-nil if current heading's buffer's filename path matches any of REGEXPS (regexp strings). -Without arguments, return non-nil if buffer is file-backed." - (when (buffer-file-name) - (cl-typecase regexps - (null t) - (list (cl-loop for regexp in regexps - thereis (string-match regexp (buffer-file-name))))))) - -(org-ql--defpred todo (&rest keywords) - "Return non-nil if current heading is a TODO item. -With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strings)." - (when-let ((state (org-get-todo-state))) - (cl-typecase keywords - (null (not (member state org-done-keywords))) - (list (member state keywords)) - (symbol (member state (symbol-value keywords))) - (otherwise (user-error "Invalid todo keywords: %s" keywords))))) - -(org-ql--defpred done () +(org-ql-defpred done () "Return non-nil if entry's TODO keyword is in `org-done-keywords'." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. - (or (apply #'org-ql--predicate-todo org-done-keywords))) + :body (or (apply #'org-ql--predicate-todo org-done-keywords))) -(org-ql--defpred (tags tags-all tags&) (&rest tags) - ;; NOTE: tags-all and tags& are "virtual" predicates that are handled by query pre-processing. - "Return non-nil if current heading has one or more of TAGS (a list of strings). -Tests both inherited and local tags." - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((inherited local) (org-ql--tags-at (point)))) - (cl-typecase tags - (null (or (tags-p inherited) - (tags-p local))) - (otherwise (or (when (tags-p inherited) - (seq-intersection tags inherited)) - (when (tags-p local) - (seq-intersection tags local)))))))) +(org-ql-defpred habit () + "Return non-nil if entry is a habit." + :preambles ((`(,predicate-names) + (list :regexp (rx bol (0+ space) ":STYLE:" (1+ space) "habit" (0+ space) eol)))) + :body (org-is-habit-p)) + +(org-ql-defpred (heading h) (&rest regexps) + "Return non-nil if current entry's heading matches all REGEXPS (regexp strings)." + :normalizers ((`(,predicate-names . ,args) + ;; "h" alias. + `(heading ,@args))) + ;; MAYBE: Adjust regexp to avoid matching in tag list. + :preambles ((`(,predicate-names ,regexp) + ;; Only one regexp: match with preamble, then let predicate confirm (because + ;; the match could be in e.g. the tags rather than the heading text). + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) + ,regexp) + 'no-group) + :query query)) + (`(,predicate-names . ,regexps) + ;; Multiple regexps: use preamble to match against first + ;; regexp, then let the predicate match the rest. + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) + ,(car regexps)) + 'no-group) + :query query))) + ;; TODO: In Org 9.2+, `org-get-heading' takes 2 more arguments. + :body (let ((heading (org-get-heading 'no-tags 'no-todo))) + (--all? (string-match it heading) regexps))) + +(org-ql-defpred level (level-or-comparator &optional level) + "Return non-nil if current heading's outline level matches arguments. +The following forms are accepted: + + (level NUMBER): Matches if heading level is NUMBER. + (level NUMBER NUMBER): Matches if heading level is equal to or between NUMBERs. + (level COMPARATOR NUMBER): Matches if heading level compares to NUMBER with COMPARATOR. + +COMPARATOR may be `<', `<=', `>', or `>='." + :normalizers ((`(,predicate-names . ,args) + ;; Arguments could be given as strings (e.g. from a non-Lisp query). + `(level ,@(--map (pcase it + ((or "<" "<=" ">" ">=" "=") + (intern it)) + ((pred stringp) (string-to-number it)) + (_ it)) + args)))) + :preambles ((`(,predicate-names ,comparator-or-num ,num) + (let ((repeat (pcase comparator-or-num + ('< `(repeat 1 ,(1- num) "*")) + ('<= `(repeat 1 ,num "*")) + ('> `(>= ,(1+ num) "*")) + ('>= `(>= ,num "*")) + ((pred integerp) `(repeat ,comparator-or-num ,num "*"))))) + (list :regexp (rx-to-string `(seq bol ,repeat " ") t) + :case-fold t))) + (`(,predicate-names ,num) + (list :regexp (rx-to-string `(seq bol (repeat ,num "*") " ") t) + :case-fold t))) + ;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for + ;; `org-outline-level'. + :body (when-let ((outline-level (org-outline-level))) + (pcase level-or-comparator + ((pred numberp) (pcase level + ('nil ;; Equality + (= outline-level level-or-comparator)) + ((pred numberp) ;; Between two levels + (>= level-or-comparator outline-level level)))) + ((pred symbolp) ;; Compare with function + (funcall level-or-comparator outline-level level))))) + +(org-ql-defpred link (&rest args) + ;; User-facing argument form: (&optional description-or-target &key description target regexp-p). + "Return non-nil if current heading contains a link matching arguments. +DESCRIPTION-OR-TARGET is matched against the link's description +and target. Alternatively, one or both of DESCRIPTION and TARGET +may be matched separately. Without arguments, return non-nil if +any link is found." + ;; NOTE: It would be preferable to avoid this manual argument parsing every time the predicate + ;; is called, but pre-processing it to a normal form gets complicated with the preamble and + ;; pre-processing, because we don't want to display a query like "(link :description-or-target + ;; "FOO")" in the view header, which would be ugly. So, since preambles are expected to be + ;; enabled nearly all of the time, in which case this function won't be called anyway, it's + ;; probably not worth rewriting code all over the place to fix this. + :preambles ((`(,predicate-names) + (list :regexp ;; Match a link with a target and optionally a description. + (rx (or bol (1+ blank)) + "[[" (1+ (not (any "]"))) "]" + (optional (seq "[" (0+ (not (any "]"))) "]")) + "]" + (or eol blank)))) + (`(,predicate-names ,(and description-or-target + (guard (not (keywordp description-or-target))))) + (list :regexp (org-ql--link-regexp :description-or-target + (regexp-quote description-or-target))) + nil) + (`(,predicate-names . ,plist) + (list :regexp (org-ql--link-regexp + :description + (when (plist-get plist :description) + (regexp-quote (plist-get plist :description))) + :target (when (plist-get plist :target) + (regexp-quote (plist-get plist :target))))) + nil)) + :body (let* (plist description-or-target description target regexp-p) + (if (not (keywordp (car args))) + (setf description-or-target (car args) + plist (cdr args)) + (setf plist args)) + (setf description (plist-get plist :description) + target (plist-get plist :description) + regexp-p (plist-get plist :regexp-p)) + (unless regexp-p + ;; NOTE: It would also be preferable to avoid regexp-quoting every time this predicate + ;; is called. Ideally that would be handled in the query pre-processing step. However, + ;; handling that properly, in combination with preparing the query preamble and whether + ;; REGEXP-P is enabled, is also complicated, so let's not. + (when description-or-target + (setf description-or-target (regexp-quote description-or-target))) + (when description + (setf description (regexp-quote description))) + (when target + (setf target (regexp-quote target)))) + (when (re-search-forward org-ql-link-regexp (org-entry-end-position) t) + (pcase description-or-target + ('nil (and (or (null target) + (string-match-p target (match-string 1))) + (or (null description) + (string-match-p description (match-string org-ql-link-description-group))))) + (_ (if (and description target) + (and (string-match-p target (match-string 1)) + (string-match-p description (match-string org-ql-link-description-group))) + (or (string-match-p description-or-target (match-string 1)) + (string-match-p description-or-target + (match-string org-ql-link-description-group))))))))) ;; MAYBE: Preambles for outline-path predicates. Not sure if possible without complicated logic. -(org-ql--defpred (outline-path olp) (&rest regexps) +(org-ql-defpred (outline-path olp) (&rest regexps) "Return non-nil if current node's outline path matches all of REGEXPS. Each string is compared as a regexp to each element of the node's outline path with `string-match'. For example, if an entry's @@ -1143,11 +1211,14 @@ the following queries: (olp \"Food\" \"Fruits\") (olp \"Fruits\" \"Grapes\") (olp \"Food\" \"Grapes\")" - (let ((entry-olp (org-ql--value-at (point) #'org-ql--outline-path))) - (cl-loop for h in regexps - always (cl-member h entry-olp :test #'string-match)))) + :normalizers ((`(,predicate-names . ,strings) + ;; Regexp quote headings. + `(outline-path ,@(mapcar #'regexp-quote strings)))) + :body (let ((entry-olp (org-ql--value-at (point) #'org-ql--outline-path))) + (cl-loop for h in regexps + always (cl-member h entry-olp :test #'string-match)))) -(org-ql--defpred (outline-path-segment olps) (&rest regexps) +(org-ql-defpred (outline-path-segment olps) (&rest regexps) "Return non-nil if current node's outline path matches segment REGEXPS. Matches REGEXPS as a contiguous segment of the outline path. Each regexp is compared to each element of the node's outline @@ -1165,118 +1236,21 @@ contiguous segment of the outline path: (olp \"Food\" \"Grape\")" ;; MAYBE: Allow anchored matching. - (org-ql--infix-p regexps (org-ql--value-at (point) #'org-ql--outline-path))) + :normalizers ((`(,(or 'outline-path-segment 'olps) . ,strings) + ;; Regexp quote headings. + `(outline-path-segment ,@(mapcar #'regexp-quote strings)))) + :body (org-ql--infix-p regexps (org-ql--value-at (point) #'org-ql--outline-path))) -(org-ql--defpred (tags-inherited tags-i itags) (&rest tags) - "Return non-nil if current heading's inherited tags include one or more of TAGS (a list of strings). -If TAGS is nil, return non-nil if heading has any inherited tags." - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((inherited _) (org-ql--tags-at (point)))) - (cl-typecase tags - (null (tags-p inherited)) - (otherwise (when (tags-p inherited) - (seq-intersection tags inherited))))))) +(org-ql-defpred path (&rest regexps) + "Return non-nil if current heading's buffer's filename path matches any of REGEXPS (regexp strings). +Without arguments, return non-nil if buffer is file-backed." + :body (when (buffer-file-name) + (cl-typecase regexps + (null t) + (list (cl-loop for regexp in regexps + thereis (string-match regexp (buffer-file-name))))))) -(org-ql--defpred (tags-local tags-l ltags) (&rest tags) - "Return non-nil if current heading's local tags include one or more of TAGS (a list of strings). -If TAGS is nil, return non-nil if heading has any local tags." - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((_ local) (org-ql--tags-at (point)))) - (cl-typecase tags - (null (tags-p local)) - (otherwise (when (tags-p local) - (seq-intersection tags local))))))) - -(org-ql--defpred (tags-regexp tags*) (&rest regexps) - "Return non-nil if current heading has tags matching one or more of REGEXPS. -Tests both inherited and local tags." - (cl-macrolet ((tags-p (tags) - `(and ,tags - (not (eq 'org-ql-nil ,tags))))) - (-let* (((inherited local) (org-ql--tags-at (point)))) - (cl-typecase regexps - (null (or (tags-p inherited) - (tags-p local))) - (otherwise (or (when (tags-p inherited) - (cl-loop for tag in inherited - thereis (cl-loop for regexp in regexps - thereis (string-match regexp tag)))) - (when (tags-p local) - (cl-loop for tag in local - thereis (cl-loop for regexp in regexps - thereis (string-match regexp tag)))))))))) - -(org-ql--defpred level (level-or-comparator &optional level) - "Return non-nil if current heading's outline level matches arguments. -The following forms are accepted: - - (level NUMBER): Matches if heading level is NUMBER. - (level NUMBER NUMBER): Matches if heading level is equal to or between NUMBERs. - (level COMPARATOR NUMBER): Matches if heading level compares to NUMBER with COMPARATOR. - -COMPARATOR may be `<', `<=', `>', or `>='." - ;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for - ;; `org-outline-level'. - (when-let ((outline-level (org-outline-level))) - (pcase level-or-comparator - ((pred numberp) (pcase level - ('nil ;; Equality - (= outline-level level-or-comparator)) - ((pred numberp) ;; Between two levels - (>= level-or-comparator outline-level level)))) - ((pred symbolp) ;; Compare with function - (funcall level-or-comparator outline-level level))))) - -(org-ql--defpred link (&rest args) - ;; User-facing argument form: (&optional description-or-target &key description target regexp-p). - "Return non-nil if current heading contains a link matching arguments. -DESCRIPTION-OR-TARGET is matched against the link's description -and target. Alternatively, one or both of DESCRIPTION and TARGET -may be matched separately. Without arguments, return non-nil if -any link is found." - ;; NOTE: It would be preferable to avoid this manual argument parsing every time the predicate - ;; is called, but pre-processing it to a normal form gets complicated with the preamble and - ;; pre-processing, because we don't want to display a query like "(link :description-or-target - ;; "FOO")" in the view header, which would be ugly. So, since preambles are expected to be - ;; enabled nearly all of the time, in which case this function won't be called anyway, it's - ;; probably not worth rewriting code all over the place to fix this. - (let* (plist description-or-target description target regexp-p) - (if (not (keywordp (car args))) - (setf description-or-target (car args) - plist (cdr args)) - (setf plist args)) - (setf description (plist-get plist :description) - target (plist-get plist :description) - regexp-p (plist-get plist :regexp-p)) - (unless regexp-p - ;; NOTE: It would also be preferable to avoid regexp-quoting every time this predicate - ;; is called. Ideally that would be handled in the query pre-processing step. However, - ;; handling that properly, in combination with preparing the query preamble and whether - ;; REGEXP-P is enabled, is also complicated, so let's not. - (when description-or-target - (setf description-or-target (regexp-quote description-or-target))) - (when description - (setf description (regexp-quote description))) - (when target - (setf target (regexp-quote target)))) - (when (re-search-forward org-ql-link-regexp (org-entry-end-position) t) - (pcase description-or-target - ('nil (and (or (null target) - (string-match-p target (match-string 1))) - (or (null description) - (string-match-p description (match-string org-ql-link-description-group))))) - (_ (if (and description target) - (and (string-match-p target (match-string 1)) - (string-match-p description (match-string org-ql-link-description-group))) - (or (string-match-p description-or-target (match-string 1)) - (string-match-p description-or-target - (match-string org-ql-link-description-group))))))))) - -(org-ql--defpred priority (&rest args) +(org-ql-defpred priority (&rest args) "Return non-nil if current heading has a certain priority. ARGS may be either a list of one or more priority letters as strings, or a comparator function symbol followed by a priority @@ -1296,6 +1270,42 @@ priority B)." ;; value. We do this because it doesn't seem very useful or intuitive for a ;; query like (priority "B") to match an item that has no priority cookie. ;; TODO: Convert priority arg(s) to numeric values in pre-processing. + :normalizers + ((`(,predicate-names ,(and (or '= '< '> '<= '>=) comparator) ,letter) + ;; Quote comparator. + `(priority ',comparator ,letter))) + + :preambles + (;; NOTE: This only accepts A, B, or C. I haven't seen + ;; other priorities in the wild, so this will do for now. + (`(,predicate-names) + ;; Any priority cookie. + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) "[#" (in "ABC") "]") t))) + (`(,predicate-names ,(and (or ''= ''< ''> ''<= ''>=) comparator) ,letter) + ;; Comparator and priority letter. + ;; NOTE: The double-quoted comparators. See below. + (let* ((priority-letters '("A" "B" "C")) + (index (-elem-index letter priority-letters)) + ;; NOTE: Higher priority == lower number. + ;; NOTE: Because we need to support both preamble-based queries and + ;; regular predicate ones, we work around an idiosyncrasy of query + ;; pre-processing by accepting both quoted and double-quoted comparator + ;; function symbols. Not the most elegant solution, but it works. + (priorities (s-join "" (pcase comparator + ((or '= ''=) (list letter)) + ((or '> ''>) (cl-subseq priority-letters 0 index)) + ((or '>= ''>=) (cl-subseq priority-letters 0 (1+ index))) + ((or '< ''<) (cl-subseq priority-letters (1+ index))) + ((or '<= ''<=) (cl-subseq priority-letters index)))))) + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (optional (1+ upper) (1+ blank)) + "[#" (in ,priorities) "]") t)))) + (`(,predicate-names . ,letters) + ;; One or more priorities. + ;; MAYBE: Disable case-folding. + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) + (optional (1+ upper) (1+ blank)) + "[#" (or ,@letters) "]") t)))) + :body (when-let* ((item-priority (save-excursion (save-match-data ;; TODO: Is the save-match-data above necessary? @@ -1317,29 +1327,32 @@ priority B)." (cl-loop for priority-arg in args thereis (= item-priority (* 1000 (- org-lowest-priority (string-to-char priority-arg))))))))) -(org-ql--defpred habit () - "Return non-nil if entry is a habit." - (org-is-habit-p)) - -(org-ql--defpred (regexp r) (&rest regexps) - "Return non-nil if current entry matches all of REGEXPS (regexp strings)." - (let ((end (or (save-excursion - (outline-next-heading)) - (point-max)))) - (save-excursion - (goto-char (line-beginning-position)) - (cl-loop for regexp in regexps - always (save-excursion - (re-search-forward regexp end t)))))) - -(org-ql--defpred (heading h) (&rest regexps) - "Return non-nil if current entry's heading matches all REGEXPS (regexp strings)." - ;; TODO: In Org 9.2+, `org-get-heading' takes 2 more arguments. - (let ((heading (org-get-heading 'no-tags 'no-todo))) - (--all? (string-match it heading) regexps))) - -(org-ql--defpred property (property &optional value) +(org-ql-defpred property (property &optional value) "Return non-nil if current entry has PROPERTY (a string), and optionally VALUE (a string)." + :normalizers ((`(,predicate-names ,property . ,value) + ;; Convert keyword property arguments to strings. Non-sexp + ;; queries result in keyword property arguments (because to do + ;; otherwise would require ugly special-casing in the parsing). + (when (keywordp property) + (setf property (substring (symbol-name property) 1))) + (cons 'property (cons property value)))) + ;; MAYBE: Should case folding be disabled for properties? What about values? + ;; MAYBE: Support (property) without args. + :preambles ((`(,predicate-names ,property ,value) + ;; We do NOT return nil, because the predicate still needs to be tested, + ;; because the regexp could match a string not inside a property drawer. + (list :regexp (rx-to-string `(seq bol (0+ space) ":" ,property ":" + (1+ space) ,value (0+ space) eol)) + :query query)) + (`(,predicate-names ,property) + ;; We do NOT return nil, because the predicate still needs to be tested, + ;; because the regexp could match a string not inside a property drawer. + ;; NOTE: The preamble only matches if there appears to be a value. + ;; A line like ":ID: " without any other text does not match. + (list :regexp (rx-to-string `(seq bol (0+ space) ":" ,property ":" (1+ space) + (minimal-match (1+ not-newline)) eol)) + :query query))) + :body (pcase property ('nil (user-error "Property matcher requires a PROPERTY argument")) (_ (pcase value @@ -1350,10 +1363,53 @@ priority B)." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) -(org-ql--defpred src (&key regexps lang) +(org-ql-defpred (regexp r) (&rest regexps) + "Return non-nil if current entry matches all of REGEXPS (regexp strings)." + :normalizers ((`(,predicate-names . ,args) + `(regexp ,@args))) + ;; MAYBE: Separate case-sensitive (Regexp) predicate. + :preambles ((`(,predicate-names ,regexp) + (list :case-fold t :regexp regexp :query t)) + (`(,predicate-names . ,regexps) + ;; Search for first regexp, then confirm with predicate. + (list :case-fold t :regexp (car regexps) :query query))) + :body + (let ((end (or (save-excursion + (outline-next-heading)) + (point-max)))) + (save-excursion + (goto-char (line-beginning-position)) + (cl-loop for regexp in regexps + always (save-excursion + (re-search-forward regexp end t)))))) + +(org-ql-defpred src (&key regexps lang) "Return non-nil if current entry contains an Org source block matching all of REGEXPS. If keyword argument LANG is non-nil, the block must be in that language." + :normalizers ((`(,predicate-names . ,args) + ;; Rewrite to use keyword args. + (-let (regexps lang keyword-index) + (cond ((plist-get args :lang) + ;; Lang given first, or only lang given. + (setf lang (plist-get args :lang) + regexps (seq-difference args (list :lang lang)))) + ((setf keyword-index (-find-index #'keywordp args)) + ;; Regexps and lang given. + (setf lang (plist-get (cl-subseq args keyword-index) :lang) + regexps (cl-subseq args 0 keyword-index))) + (t ;; Only regexps given. + (setf regexps args))) + (when regexps + ;; This feels awkward and wrong, but we have to quote lists + ;; and avoid quoting nil. There must be a better way. + (setf regexps `(',regexps))) + `(src :lang ,lang :regexps ,@regexps)))) + :preambles ((`(,predicate-names . ,args) + (list :regexp (org-ql--format-src-block-regexp (plist-get args :lang)) + ;; Always check contents with predicate. + :query query))) + :body (catch 'return (save-excursion (save-match-data @@ -1375,6 +1431,101 @@ language." ;; No regexps to check: return non-nil. t)))))) +(org-ql-defpred (tags) (&rest tags) + "Return non-nil if current heading has one or more of TAGS (a list of strings). +Tests both inherited and local tags." + ;; MAYBE: -all versions for inherited and local. + :body (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((inherited local) (org-ql--tags-at (point)))) + (cl-typecase tags + (null (or (tags-p inherited) + (tags-p local))) + (otherwise (or (when (tags-p inherited) + (seq-intersection tags inherited)) + (when (tags-p local) + (seq-intersection tags local)))))))) + +(org-ql-defpred (tags-all tags&) (&rest tags) + "Return non-nil if current heading has all of TAGS (a list of strings). +Tests both inherited and local tags." + ;; MAYBE: -all versions for inherited and local. + :normalizers ((`(,predicate-names) `(tags)) + (`(,predicate-names . ,tags) `(and ,@(--map `(tags ,it) tags)))) + :body (apply #'org-ql--predicate-tags tags)) + +(org-ql-defpred (tags-inherited inherited-tags tags-i itags) (&rest tags) + "Return non-nil if current heading's inherited tags include one or more of TAGS (a list of strings). +If TAGS is nil, return non-nil if heading has any inherited tags." + :normalizers ((`(,predicate-names . ,tags) + `(tags-inherited ,@tags)) + (`(,predicate-names) + `(tags-inherited))) + :body (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((inherited _) (org-ql--tags-at (point)))) + (cl-typecase tags + (null (tags-p inherited)) + (otherwise (when (tags-p inherited) + (seq-intersection tags inherited))))))) + +(org-ql-defpred (tags-local local-tags tags-l ltags) (&rest tags) + "Return non-nil if current heading's local tags include one or more of TAGS (a list of strings). +If TAGS is nil, return non-nil if heading has any local tags." + :normalizers ((`(,predicate-names) `(tags-local)) + (`(,predicate-names . ,tags) `(tags-local ,@tags))) + :preambles ((`(,predicate-names . ,(and tags (guard tags))) + ;; When searching for local, non-inherited tags, we can + ;; search directly to headings containing one of the tags. + (list :regexp (rx-to-string `(seq bol (1+ "*") (1+ space) (1+ not-newline) + ":" (or ,@tags) ":") + t) + :query t))) + :body (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((_ local) (org-ql--tags-at (point)))) + (cl-typecase tags + (null (tags-p local)) + (otherwise (when (tags-p local) + (seq-intersection tags local))))))) + +(org-ql-defpred (tags-regexp tags*) (&rest regexps) + "Return non-nil if current heading has tags matching one or more of REGEXPS. +Tests both inherited and local tags." + :normalizers ((`(,predicate-names . ,regexps) + `(tags-regexp ,@regexps))) + :body (cl-macrolet ((tags-p (tags) + `(and ,tags + (not (eq 'org-ql-nil ,tags))))) + (-let* (((inherited local) (org-ql--tags-at (point)))) + (cl-typecase regexps + (null (or (tags-p inherited) + (tags-p local))) + (otherwise (or (when (tags-p inherited) + (cl-loop for tag in inherited + thereis (cl-loop for regexp in regexps + thereis (string-match regexp tag)))) + (when (tags-p local) + (cl-loop for tag in local + thereis (cl-loop for regexp in regexps + thereis (string-match regexp tag)))))))))) + +(org-ql-defpred todo (&rest keywords) + "Return non-nil if current heading is a TODO item. +With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strings)." + ;; TODO: Can we make a preamble for plain (todo) queries? + :preambles ((`(,predicate-names . ,(and todo-keywords (guard todo-keywords))) + (list :case-fold nil :regexp (rx-to-string `(seq bol (1+ "*") (1+ space) (or ,@todo-keywords) (or " " eol)) t)))) + :body (when-let ((state (org-get-todo-state))) + (cl-typecase keywords + (null (not (member state org-done-keywords))) + (list (member state keywords)) + (symbol (member state (symbol-value keywords))) + (otherwise (user-error "Invalid todo keywords: %s" keywords))))) + ;;;;;; Ancestor/descendant ;; These predicates search ancestor and descendant headings for sub-queries. @@ -1393,14 +1544,20 @@ language." ;; rather than user-facing, since their arguments are predicates provided ;; automatically by `--pre-process-query'. -(org-ql--defpred ancestors (predicate) +(org-ql-defpred ancestors (predicate) "Return non-nil if any of current entry's ancestors satisfy PREDICATE." + :normalizers ((`(,predicate-names ,query) `(ancestors ,(org-ql--query-predicate (rec query)))) + (`(,predicate-names) '(ancestors (lambda () t)))) + :body (org-with-wide-buffer (cl-loop while (org-up-heading-safe) thereis (org-ql--value-at (point) predicate)))) -(org-ql--defpred parent (predicate) +(org-ql-defpred parent (predicate) "Return non-nil if the current entry's parent satisfies PREDICATE." + :normalizers ((`(,predicate-names ,query) `(parent ,(org-ql--query-predicate (rec query)))) + (`(,predicate-names) '(parent (lambda () t)))) + :body (org-with-wide-buffer (when (org-up-heading-safe) (org-ql--value-at (point) predicate)))) @@ -1411,8 +1568,12 @@ language." ;; on the Org file being searched and the sub-query, performance could be better or ;; worse. It should be benchmarked extensively before so changing the implementation. -(org-ql--defpred children (query) +(org-ql-defpred children (query) "Return non-nil if current entry has children matching QUERY." + ;; Quote children queries so the user doesn't have to. + :normalizers ((`(,predicate-names ,query) `(children ',query)) + (`(,predicate-names) '(children (lambda () t)))) + :body (org-with-wide-buffer ;; Widening is needed if inside an "ancestors" query (org-narrow-to-subtree) @@ -1432,10 +1593,13 @@ language." :action (lambda () (throw 'found t)))))))) -(org-ql--defpred descendants (query) +(org-ql-defpred descendants (query) "Return non-nil if current entry has descendants matching QUERY." ;; TODO: This could probably be rewritten like the `ancestors' predicate, ;; which avoids calling `org-ql-select' recursively and its associated overhead. + :normalizers ((`(,predicate-names ,query) `(descendants ',query)) + (`(,predicate-names) '(descendants (lambda () t)))) + :body (org-with-wide-buffer (org-narrow-to-subtree) (when (org-goto-first-child) @@ -1454,13 +1618,13 @@ language." ;; NOTE: These docstrings apply to the functions defined by `org-ql--defpref', ;; not necessarily to the way users are expected to call them in queries. The -;; queries are pre-processed by `org-ql--pre-process-query' to handle +;; queries are pre-processed by `org-ql--normalize-query' to handle ;; arguments which are constant during a query's execution. ;; TODO: Update the macro to define a user-facing docstring so I don't ;; have to manually update the documentation. -(org-ql--defpred clocked (&key from to _on) +(org-ql-defpred clocked (&key from to _on) ;; The underscore before `on' prevents "unused lexical variable" ;; warnings, because we pre-process that argument in a macro before ;; this function is called. @@ -1477,9 +1641,20 @@ If ON, return non-nil if entry has a timestamp on date ON. FROM, TO, and ON should be either `ts' structs, or strings parseable by `parse-time-string' which may omit the time value." + :normalizers ((`(,predicate-names ,(and num-days (pred numberp))) + ;; (clocked) and (closed) implicitly look into the past. + (let ((from (->> (ts-now) + (ts-adjust 'day (* -1 num-days)) + (ts-apply :hour 0 :minute 0 :second 0)))) + `(clocked :from ,from)))) + :preambles ((`(,predicate-names ,(pred numberp)) + (list :regexp org-ql-clock-regexp :query t)) + (`(,predicate-names) + (list :regexp org-ql-clock-regexp :query t))) + :body (org-ql--predicate-ts :from from :to to :regexp org-ql-clock-regexp :match-group 1)) -(org-ql--defpred closed (&key from to _on) +(org-ql-defpred closed (&key from to _on) ;; The underscore before `on' prevents "unused lexical variable" ;; warnings, because we pre-process that argument in a macro before ;; this function is called. @@ -1496,10 +1671,20 @@ If ON, return non-nil if entry has a timestamp on date ON. FROM, TO, and ON should be either `ts' structs, or strings parseable by `parse-time-string' which may omit the time value." + :normalizers ((`(,predicate-names ,(and num-days (pred numberp))) + ;; (clocked) and (closed) implicitly look into the past. + (let ((from (->> (ts-now) + (ts-adjust 'day (* -1 num-days)) + (ts-apply :hour 0 :minute 0 :second 0)))) + `(closed :from ,from)))) + :preambles ((`(,predicate-names . ,_) + ;; Predicate still needs testing. + (list :regexp org-closed-time-regexp :query query))) + :body (org-ql--predicate-ts :from from :to to :regexp org-closed-time-regexp :match-group 1 :limit (line-end-position 2))) -(org-ql--defpred deadline (&key from to _on) +(org-ql-defpred deadline (&key from to _on) ;; The underscore before `on' prevents "unused lexical variable" ;; warnings, because we pre-process that argument in a macro before ;; this function is called. @@ -1516,11 +1701,29 @@ If ON, return non-nil if entry has a timestamp on date ON. FROM, TO, and ON should be either `ts' structs, or strings parseable by `parse-time-string' which may omit the time value." + :normalizers ((`(,predicate-names auto) + ;; Use `org-deadline-warning-days' as the :to arg. + (let ((to (->> (ts-now) + (ts-adjust 'day org-deadline-warning-days) + (ts-apply :hour 23 :minute 59 :second 59)))) + `(deadline-warning :to ,to))) + (`(,predicate-names ,(and num-days (pred numberp))) + (let ((to (->> (ts-now) + (ts-adjust 'day num-days) + (ts-apply :hour 23 :minute 59 :second 59)))) + `(deadline :to ,to)))) + ;; NOTE: Does this normalizer cause the preamble to not be used? (Adding one to the deadline-warning definition to be sure.) + :preambles ((`(,predicate-names . ,_) + (list :regexp org-deadline-time-regexp :query query))) + :body (org-ql--predicate-ts :from from :to to :regexp org-deadline-time-regexp :match-group 1 :limit (line-end-position 2))) -(org-ql--defpred deadline-warning (&key from to) +(org-ql-defpred deadline-warning (&key from to) "Internal selector used to handle `org-deadline-warning-days' and deadlines with warning periods." + :preambles ((`(,predicate-names . ,_) + (list :regexp org-deadline-time-regexp :query query))) + :body (save-excursion (forward-line 1) (when (re-search-forward org-deadline-time-regexp (line-end-position) t) @@ -1535,7 +1738,7 @@ parseable by `parse-time-string' which may omit the time value." ((_timestamp (&keys :warning-value :warning-unit)) deadline-ts-element) (ts (ts-parse-org-element deadline-ts-element))) (pcase warning-unit - ('nil ;; Deadline has no warning unit: compare with ts passed in. + ('nil ;; Deadline has no warning unit: compare with ts passed in. (cond ((and from to) (ts-in from to ts)) (from (ts<= from ts)) (to (ts<= ts to)))) @@ -1544,7 +1747,7 @@ parseable by `parse-time-string' which may omit the time value." (ts<= (->> ts (ts-adjust unit (- warning-value))) org-ql--today)) ('week (ts<= (->> ts (ts-adjust 'day (* -7 warning-value))) org-ql--today))))))) -(org-ql--defpred planning (&key from to _on) +(org-ql-defpred planning (&key from to _on) ;; The underscore before `on' prevents "unused lexical variable" ;; warnings, because we pre-process that argument in a macro before ;; this function is called. @@ -1561,10 +1764,18 @@ If ON, return non-nil if entry has a timestamp on date ON. FROM, TO, and ON should be either `ts' structs, or strings parseable by `parse-time-string' which may omit the time value." + :normalizers ((`(,predicate-names ,(and num-days (pred numberp))) + (let ((to (->> (ts-now) + (ts-adjust 'day num-days) + (ts-apply :hour 23 :minute 59 :second 59)))) + `(planning :to ,to)))) + :preambles ((`(,predicate-names . ,_) + (list :regexp org-ql-planning-regexp :query query))) + :body (org-ql--predicate-ts :from from :to to :regexp org-ql-planning-regexp :match-group 1 :limit (line-end-position 2))) -(org-ql--defpred scheduled (&key from to _on) +(org-ql-defpred scheduled (&key from to _on) ;; The underscore before `on' prevents "unused lexical variable" ;; warnings, because we pre-process that argument in a macro before ;; this function is called. @@ -1581,12 +1792,20 @@ If ON, return non-nil if entry has a timestamp on date ON. FROM, TO, and ON should be either `ts' structs, or strings parseable by `parse-time-string' which may omit the time value." + :normalizers ((`(,predicate-names ,(and num-days (pred numberp))) + (let ((to (->> (ts-now) + (ts-adjust 'day num-days) + (ts-apply :hour 23 :minute 59 :second 59)))) + `(scheduled :to ,to)))) + :preambles ((`(,predicate-names . ,_) + (list :regexp org-scheduled-time-regexp :query query))) + :body (org-ql--predicate-ts :from from :to to :regexp org-scheduled-time-regexp :match-group 1 :limit (line-end-position 2))) -(org-ql--defpred (ts ts-active ts-a ts-inactive ts-i) +(org-ql-defpred (ts ts-active ts-a ts-inactive ts-i) (&key from to _on regexp (match-group 0) (limit (org-entry-end-position))) - ;; NOTE: Arguments to this predicate are pre-processed in `org-ql--pre-process-query'. + ;; NOTE: Arguments to this predicate are pre-processed in `org-ql--normalize-query'. ;; The underscore before `on' prevents "unused lexical variable" warnings due to the ;; pre-processing converting that argument to FROM and TO. The `regexp' argument is ;; also provided by the pre-processing and is not to be given by the user. FROM and @@ -1613,7 +1832,23 @@ the end of the entry, i.e. the position returned by `org-entry-end-position', but for certain searches it should be bound to a different positiion, e.g. for planning lines, the end of the line after the heading." + ;; MAYBE: Define active/inactive ones separately? + :normalizers ((`(,(or 'ts-active 'ts-a) . ,rest) `(ts :type active ,@rest)) + (`(,(or 'ts-inactive 'ts-i) . ,rest) `(ts :type inactive ,@rest))) + :preambles ((`(,predicate-names . ,rest) + (list :regexp (pcase (plist-get rest :type) + ((or 'nil 'both) org-tsr-regexp-both) + ('active org-tsr-regexp) + ('inactive org-ql-tsr-regexp-inactive)) + ;; Predicate needs testing only when args are present. + :query (-let (((&keys :from :to :on) rest)) + ;; FIXME: This used to be (when (or from to on) query), but that doesn't seem right, so I + ;; changed it to this if, and the tests pass either way. Might deserve a little scrutiny. + (if (or from to on) + query + t))))) ;; TODO: DRY this with the clocked predicate. + :body (cl-macrolet ((next-timestamp () `(when (re-search-forward regexp limit t) (ts-parse-org (match-string match-group)))) @@ -1627,6 +1862,14 @@ of the line after the heading." (from (test-timestamps (ts<= from next-ts))) (to (test-timestamps (ts<= next-ts to))))))) +;; Predicates defined: stop deferring and define normalizer and preamble functions now. +(setf org-ql-defpred-defer nil) +;; Reversing preserves the order in which they were defined. +;; Generally it shouldn't matter, but it might... +(org-ql--define-normalize-query-fn (reverse org-ql-predicates)) +(org-ql--define-query-preamble-fn (reverse org-ql-predicates)) +(org-ql--def-query-string-to-sexp-fn (reverse org-ql-predicates)) + ;;;;; Sorting ;; TODO: These appear to work properly, but it would be good to have tests for them. @@ -1720,94 +1963,6 @@ element should be a regexp string." always (string-match i l)) do (pop list))) -;;;;; Plain query parsing - -;; This section implements parsing of "plain," non-Lisp queries using the `peg' -;; library. NOTE: This needs to appear after the predicates are defined. - -;; TODO: Rename "plain" to "string", or something like that. - -(require 'peg) - -;; Fix compiler warnings probably caused by `peg' not using lexical-binding. -;; TODO: File bug report upstream. -(defvar peg-errors) -(defvar peg-stack) - -(defmacro org-ql--peg-parse-string (rules string &optional noerror) - "Parse STRING according to RULES." - ;; This sentence was in the docstring but Checkdoc is complaining, - ;; so moving it to a comment: "If NOERROR is non-nil, push nil - ;; resp. t if the parse failed resp. succeded instead of signaling - ;; an error." - - ;; Unfortunately, this macro was moved to peg-tests.el, so we copy it here. - `(with-temp-buffer - (insert ,string) - (goto-char (point-min)) - ,(if noerror - (let ((entry (make-symbol "entry")) - (start (caar rules))) - `(peg-parse (,entry (or (and ,start `(-- t)) "")) - . ,rules)) - `(peg-parse . ,rules)))) - -(cl-eval-when (compile load eval) - ;; This `eval-when' is necessary, otherwise the macro does not define - ;; the function correctly, apparently because `org-ql-predicates' - ;; ends up being not defined correctly at expansion time. - - (defmacro org-ql--def-plain-query-fn () - "Define function `org-ql--plain-query'. -Builds the PEG expression using predicates defined in -`org-ql-predicates' and `org-ql-predicates-extra-aliases'." - (let* ((predicates (--map (symbol-name (plist-get it :name)) - org-ql-predicates)) - (aliases (->> org-ql-predicates - (--map (plist-get it :aliases)) - -non-nil - -flatten - (-map #'symbol-name))) - (predicates (->> (append predicates aliases) - -uniq - ;; Sort the keywords longest-first to work around what seems to be an - ;; obscure bug in `peg': when one keyword is a substring of another, - ;; and the shorter one is listed first, the shorter one fails to match. - (-sort (-on #'> #'length))))) - `(cl-defun org-ql--plain-query (input &optional (boolean 'and)) - "Return query parsed from plain query string INPUT. -Multiple predicates are combined with BOOLEAN." - (unless (s-blank-str? input) - (let* ((query (org-ql--peg-parse-string - ((query (+ term - (opt (+ (syntax-class whitespace) (any))))) - (term (or (and negation (list positive-term) - ;; This is a bit confusing, but it seems to work. There's probably a better way. - `(pred -- (list 'not (car pred)))) - positive-term)) - (positive-term (or (and predicate-with-args `(pred args -- (cons (intern pred) args))) - (and predicate-without-args `(pred -- (list (intern pred)))) - (and plain-string `(s -- (list 'regexp s))))) - (plain-string (or quoted-arg unquoted-arg)) - (predicate-with-args (substring predicate) ":" args) - (predicate-without-args (substring predicate) ":") - (predicate (or ,@predicates)) - (args (list (+ (and (or keyword-arg quoted-arg unquoted-arg) (opt separator))))) - (keyword-arg (and keyword "=" `(kw -- (intern (concat ":" kw))))) - (keyword (substring (+ (not (or separator "=" "\"" (syntax-class whitespace))) (any)))) - (quoted-arg "\"" (substring (+ (not (or separator "\"")) (any))) "\"") - (unquoted-arg (substring (+ (not (or separator "\"" (syntax-class whitespace))) (any)))) - (negation "!") - (separator "," )) - input 'noerror))) - ;; Discard the t that `peg-parse-string' always returns as the first - ;; element. I don't know what it means, but we don't want it. - (if (> (length (cdr query)) 1) - (cons boolean (nreverse (cdr query))) - (cadr query))))))) - - (org-ql--def-plain-query-fn)) - ;; And now we go the other direction... (defun org-ql--query-sexp-to-string (query) diff --git a/org-ql.info b/org-ql.info index abfce7a..1d693c3 100644 --- a/org-ql.info +++ b/org-ql.info @@ -63,6 +63,7 @@ Functions / Macros * Agenda-like views:: * Listing / acting-on results:: +* Custom predicates:: Changelog @@ -565,11 +566,13 @@ File: README.info, Node: Functions / Macros, Next: Dynamic block, Prev: Queri • • • - • • • + • • • • • + • * Menu: * Agenda-like views:: * Listing / acting-on results:: +* Custom predicates::  File: README.info, Node: Agenda-like views, Next: Listing / acting-on results, Up: Functions / Macros @@ -606,7 +609,7 @@ File: README.info, Node: Agenda-like views, Next: Listing / acting-on results, the block header, otherwise the header is formed automatically.  -File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, Up: Functions / Macros +File: README.info, Node: Listing / acting-on results, Next: Custom predicates, Prev: Agenda-like views, Up: Functions / Macros 4.3.2 Listing / acting-on results --------------------------------- @@ -737,6 +740,84 @@ File: README.info, Node: Listing / acting-on results, Prev: Agenda-like views, Expands into a call to ‘org-ql-select’ with the same arguments. For convenience, arguments should be unquoted. + +File: README.info, Node: Custom predicates, Prev: Listing / acting-on results, Up: Functions / Macros + +4.3.3 Custom predicates +----------------------- + + • See: Custom predicate tutorial (examples/defpred.org) + + 1. Macro: org-ql-defpred + + _Arguments:_ ‘(name args docstring &key body preambles + normalizers)’ + + Define an ‘org-ql’ selector predicate named + ‘org-ql--predicate-NAME’. ‘NAME’ may be a symbol or a list of + symbols: if a list, the first is used as ‘NAME’ and the rest are + aliases. ‘A’ function is only created for ‘NAME’, not for aliases, + so a normalizer should be used to replace aliases with ‘NAME’ in + queries (keep reading). + + ‘ARGS’ is a ‘cl-defun’-style argument list. ‘DOCSTRING’ is the + function’s docstring. + + ‘BODY’ is the body of the predicate. It will be evaluated with + point on the beginning of an Org heading and should return non-nil + if the heading’s entry is a match. + + ‘PREAMBLES’ and ‘NORMALIZERS’ are lists of ‘pcase’ forms matched + against Org ‘QL’ query sexps. They are spliced into ‘pcase’ forms + in the definitions of the functions ‘org-ql--query-preamble’ and + ‘org-ql--normalize-query’, which see. Those functions are + redefined when this macro is expanded, unless variable + ‘org-ql-defpred-defer’ is non-nil, in which case those functions + should be redefined manually after defining predicates by calling + ‘org-ql--define-query-preamble-fn’ and + ‘org-ql--define-normalize-query-fn’. + + ‘NORMALIZERS’ are used to normalize query expressions to standard + forms. For example, when the predicate has aliases, the aliases + should be replaced with predicate names using a normalizer. Also, + predicate arguments may be put into a more optimal form so that the + predicate has less work to do at query time. + + ‘PREAMBLES’ refer to regular expressions which may be used to + search through a buffer directly to a potential match rather than + testing the predicate body on each heading. (Naming things is + hard.) In each ‘pcase’ form in ‘PREAMBLES’, the ‘pcase’ expression + (not the pattern) should be a plist with the following keys, each + value of which should be an expression which may refer to variables + bound in the pattern: + + ‘:regexp’ Regular expression which searches directly to a potential + match. + + ‘:case-fold’ Bound to ‘case-fold-search’ around the regexp search. + + ‘:query’ Expression which should replace the query expression, or + ‘query’ if it should not be changed (e.g. if the regexp is + insufficient to determine whether a heading matches, in which case + the predicate’s body needs to be tested on the heading). If the + regexp guarantees a match, this may be simply ‘t’, leaving the + query expression with no work to do, which improves performance. + + For convenience, within the ‘pcase’ patterns, the symbol + ‘predicate-names’ is a special form which is replaced with a + pattern matching any of the predicate’s name and aliases. For + example, if ‘NAME’ were: + + ‘(heading h)’ + + Then if ‘NORMALIZERS’ were: + + ‘((`(,predicate-names . ,args) `(heading ,@args)))’ + + It would be expanded to: + + ‘((`(,(or 'heading 'h) . ,args) `(heading ,@args)))’ +  File: README.info, Node: Dynamic block, Next: Links, Prev: Functions / Macros, Up: Usage @@ -859,7 +940,15 @@ File: README.info, Node: 06-pre, Next: 05, Up: Changelog 5.1 0.6-pre =========== -Nothing new yet. +*Added* + • Macro org-ql-defpred, used to define search predicates. (See + tutorial (examples/defpred.org).) + + *Internal* + • Predicates are now defined more cleanly with a macro + (org-ql-defpred) that consolidates functionality related to each + predicate. This will also allow users to more easily define custom + predicates.  File: README.info, Node: 05, Next: 049, Prev: 06-pre, Up: Changelog @@ -1348,54 +1437,55 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1606 -Node: Screenshots1729 -Node: Installation1847 -Node: Quelpa2485 -Node: Usage2928 -Node: Commands3326 -Node: org-ql-search3799 -Node: helm-org-ql5449 -Node: org-ql-view5861 -Node: org-ql-view-sidebar6361 -Node: org-ql-view-recent-items6717 -Node: org-ql-sparse-tree7201 -Node: Queries8001 -Node: Non-sexp query syntax9112 -Node: General predicates10819 -Node: Ancestor/descendant predicates16232 -Node: Date/time predicates17360 -Node: Functions / Macros20015 -Node: Agenda-like views20270 -Node: Listing / acting-on results21675 -Node: Dynamic block26870 -Node: Links29568 -Node: Tips30255 -Node: Changelog30573 -Node: 06-pre31269 -Node: 0531375 -Node: 04932852 -Node: 04833126 -Node: 04733473 -Node: 04633868 -Node: 04534268 -Node: 04434627 -Node: 04334984 -Node: 04235179 -Node: 04135340 -Node: 0435581 -Node: 03239514 -Node: 03139893 -Node: 0340090 -Node: 02343065 -Node: 02243293 -Node: 02143561 -Node: 0243760 -Node: 0147795 -Node: Notes47896 -Node: Comparison with Org Agenda searches48058 -Node: org-sidebar48930 -Node: License49209 +Node: Contents1628 +Node: Screenshots1751 +Node: Installation1869 +Node: Quelpa2507 +Node: Usage2950 +Node: Commands3348 +Node: org-ql-search3821 +Node: helm-org-ql5471 +Node: org-ql-view5883 +Node: org-ql-view-sidebar6383 +Node: org-ql-view-recent-items6739 +Node: org-ql-sparse-tree7223 +Node: Queries8023 +Node: Non-sexp query syntax9134 +Node: General predicates10841 +Node: Ancestor/descendant predicates16254 +Node: Date/time predicates17382 +Node: Functions / Macros20037 +Node: Agenda-like views20335 +Node: Listing / acting-on results21740 +Node: Custom predicates26961 +Node: Dynamic block30452 +Node: Links33150 +Node: Tips33837 +Node: Changelog34155 +Node: 06-pre34851 +Node: 0535291 +Node: 04936768 +Node: 04837042 +Node: 04737389 +Node: 04637784 +Node: 04538184 +Node: 04438543 +Node: 04338900 +Node: 04239095 +Node: 04139256 +Node: 0439497 +Node: 03243430 +Node: 03143809 +Node: 0344006 +Node: 02346981 +Node: 02247209 +Node: 02147477 +Node: 0247676 +Node: 0151711 +Node: Notes51812 +Node: Comparison with Org Agenda searches51974 +Node: org-sidebar52846 +Node: License53125  End Tag Table diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index c9d560e..3aebd3e 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -50,7 +50,7 @@ Set at runtime by test suite.") ('org-ql 'org-ql) ('org-ql-expect t) ('org-ql--query-preamble 'query-preamble) - ('org-ql--pre-process-query t) + ('org-ql--normalize-query t) (_ nil))) (result (pcase sexp (`(org-ql-expect ,args) @@ -63,7 +63,7 @@ Set at runtime by test suite.") :action (org-ql-test-org-get-heading)))) (`(org-ql-select . _) (org-ql-test--format-result--ql sexp)) (`(org-ql--query-preamble . _) (org-ql-test--format-result--query-preamble sexp)) - (`(org-ql--pre-process-query . _) (format "'%S" (eval sexp))) + (`(org-ql--normalize-query . _) (format "'%S" (eval sexp))) (_ nil)))) (progn (backward-char 1) @@ -222,61 +222,75 @@ RESULTS should be a list of strings as returned by (describe "(level)" (it "with one level" - (expect (org-ql--pre-process-query '(level "1")) + (expect (org-ql--normalize-query '(level "1")) :to-equal '(level 1))) (it "with two levels" - (expect (org-ql--pre-process-query '(level "1" "2")) + (expect (org-ql--normalize-query '(level "1" "2")) :to-equal '(level 1 2))) (it "with a comparator and a level" - (expect (org-ql--pre-process-query '(level ">" "1")) + (expect (org-ql--normalize-query '(level ">" "1")) :to-equal '(level > 1)))) (describe "(link)" (it "with one argument" - (expect (org-ql--pre-process-query '(link "DESC-OR-TARGET")) + (expect (org-ql--normalize-query '(link "DESC-OR-TARGET")) :to-equal '(link "DESC-OR-TARGET"))) (it "with one argument and :regexp-p" - (expect (org-ql--pre-process-query '(link "DESC-OR-TARGET" :regexp-p t)) + (expect (org-ql--normalize-query '(link "DESC-OR-TARGET" :regexp-p t)) :to-equal '(link "DESC-OR-TARGET" :regexp-p t))) (it "with keyword arguments" - (expect (org-ql--pre-process-query '(link :description "DESCRIPTION" :target "TARGET" - :regexp-p t)) + (expect (org-ql--normalize-query '(link :description "DESCRIPTION" :target "TARGET" + :regexp-p t)) :to-equal '(link :description "DESCRIPTION" :target "TARGET" :regexp-p t)))) - (expect (org-ql--pre-process-query '(and "string1" "string2")) + (expect (org-ql--normalize-query '(and "string1" "string2")) :to-equal '(and (regexp "string1") (regexp "string2"))) - (expect (org-ql--pre-process-query '(or "string1" "string2")) + (expect (org-ql--normalize-query '(or "string1" "string2")) :to-equal '(or (regexp "string1") (regexp "string2"))) - (expect (org-ql--pre-process-query '(and (todo "TODO") - (or "string1" "string2"))) + (expect (org-ql--normalize-query '(and (todo "TODO") + (or "string1" "string2"))) :to-equal '(and (todo "TODO") (or (regexp "string1") (regexp "string2")))) - (expect (org-ql--pre-process-query '(when (todo "TODO") - (or "string1" "string2"))) + (expect (org-ql--normalize-query '(when (todo "TODO") + (or "string1" "string2"))) :to-equal '(when (todo "TODO") (or (regexp "string1") (regexp "string2")))) - (expect (org-ql--pre-process-query '(when "string-cond1" - (or "string1" "string2"))) + (expect (org-ql--normalize-query '(when "string-cond1" + (or "string1" "string2"))) :to-equal '(when (regexp "string-cond1") (or (regexp "string1") (regexp "string2")))) - (expect (org-ql--pre-process-query '(when (and "string-cond1" "string-cond2") - (or "string1" "string2"))) + (expect (org-ql--normalize-query '(when (and "string-cond1" "string-cond2") + (or "string1" "string2"))) :to-equal '(when (and (regexp "string-cond1") (regexp "string-cond2")) (or (regexp "string1") (regexp "string2")))) - (expect (org-ql--pre-process-query '(unless (and "stringcondition1" "stringcond2") - (or "string1" "string2"))) + (expect (org-ql--normalize-query '(unless (and "stringcondition1" "stringcond2") + (or "string1" "string2"))) :to-equal '(unless (and (regexp "stringcondition1") (regexp "stringcond2")) (or (regexp "string1") (regexp "string2")))) - (expect (org-ql--pre-process-query '(or (ts-active :on "2019-01-01") - (ts-a :on "2019-01-01") - (ts-inactive :on "2019-01-01") - (ts-i :on "2019-01-01"))) + (expect (org-ql--normalize-query '(or (ts-active :on "2019-01-01") + (ts-a :on "2019-01-01") + (ts-inactive :on "2019-01-01") + (ts-i :on "2019-01-01"))) :to-equal '(or (ts :type active :on "2019-01-01") (ts :type active :on "2019-01-01") (ts :type inactive :on "2019-01-01") (ts :type inactive :on "2019-01-01")))) - (describe "Query optimizing" + (describe "Query preambles" ;; TODO: Other predicates. + (describe "(clocked)" + (it "without arguments" + (expect (org-ql--query-preamble '(clocked)) + :to-equal (list :query t + :preamble org-ql-clock-regexp + :preamble-case-fold nil))) + (it "with a number of days" + (expect (org-ql--query-preamble '(clocked 1)) + :to-equal (list :query t + :preamble org-ql-clock-regexp + :preamble-case-fold nil))) + ;; TODO: Other arguments for (clocked). + ) + (describe "(level)" (it "with a number" (expect (org-ql--query-preamble '(level 2)) @@ -314,60 +328,60 @@ RESULTS should be a list of strings as returned by ;; TODO: Other predicates. (it "Negated terms" - (expect (org-ql--plain-query "todo: !todo:CHECK,SOMEDAY") + (expect (org-ql--query-string-to-sexp "todo: !todo:CHECK,SOMEDAY") :to-equal '(and (todo) (not (todo "CHECK" "SOMEDAY")))) - (expect (org-ql--plain-query "!todo:CHECK,SOMEDAY todo:") + (expect (org-ql--query-string-to-sexp "!todo:CHECK,SOMEDAY todo:") :to-equal '(and (not (todo "CHECK" "SOMEDAY")) (todo))) - (expect (org-ql--plain-query "tags:universe !moon") + (expect (org-ql--query-string-to-sexp "tags:universe !moon") :to-equal '(and (tags "universe") (not (regexp "moon")))) - (expect (org-ql--plain-query "!moon tags:universe") + (expect (org-ql--query-string-to-sexp "!moon tags:universe") :to-equal '(and (not (regexp "moon")) (tags "universe"))) - (expect (org-ql--plain-query "mars !ts:on=today") + (expect (org-ql--query-string-to-sexp "mars !ts:on=today") :to-equal '(and (regexp "mars") (not (ts :on "today")))) - (expect (org-ql--plain-query "!\"quoted phrase\"") + (expect (org-ql--query-string-to-sexp "!\"quoted phrase\"") :to-equal '(not (regexp "quoted phrase")))) (it "Regexp predicates" - (expect (org-ql--plain-query "scheduled") + (expect (org-ql--query-string-to-sexp "scheduled") ;; No colon after keyword, so not a predicate query. :to-equal '(regexp "scheduled")) - (expect (org-ql--plain-query "\"quoted phrase\"") + (expect (org-ql--query-string-to-sexp "\"quoted phrase\"") :to-equal '(regexp "quoted phrase")) - (expect (org-ql--plain-query "regexp:word") + (expect (org-ql--query-string-to-sexp "regexp:word") :to-equal '(regexp "word")) - (expect (org-ql--plain-query "regexp:\"quoted phrase\"") + (expect (org-ql--query-string-to-sexp "regexp:\"quoted phrase\"") :to-equal '(regexp "quoted phrase"))) (it "Timestamp-based predicates" - (expect (org-ql--plain-query "scheduled:on=2017-07-07") + (expect (org-ql--query-string-to-sexp "scheduled:on=2017-07-07") :to-equal '(scheduled :on "2017-07-07")) - (expect (org-ql--plain-query "deadline:from=2017-07-07,to=2017-07-09") + (expect (org-ql--query-string-to-sexp "deadline:from=2017-07-07,to=2017-07-09") :to-equal '(deadline :from "2017-07-07" :to "2017-07-09")) - (expect (org-ql--plain-query "planning:from=2017-07-07") + (expect (org-ql--query-string-to-sexp "planning:from=2017-07-07") :to-equal '(planning :from "2017-07-07")) - (expect (org-ql--plain-query "closed:from=2017-07-07") + (expect (org-ql--query-string-to-sexp "closed:from=2017-07-07") :to-equal '(closed :from "2017-07-07")) - (expect (org-ql--plain-query "ts-active:to=2017-07-07") + (expect (org-ql--query-string-to-sexp "ts-active:to=2017-07-07") :to-equal '(ts-active :to "2017-07-07")) - (expect (org-ql--plain-query "ts-inactive:to=2017-07-07") + (expect (org-ql--query-string-to-sexp "ts-inactive:to=2017-07-07") :to-equal '(ts-inactive :to "2017-07-07")) - (expect (org-ql--plain-query "ts-a:to=2017-07-07") + (expect (org-ql--query-string-to-sexp "ts-a:to=2017-07-07") :to-equal '(ts-a :to "2017-07-07")) - (expect (org-ql--plain-query "ts-i:on=2017-07-07") + (expect (org-ql--query-string-to-sexp "ts-i:on=2017-07-07") :to-equal '(ts-i :on "2017-07-07")) - (expect (org-ql--plain-query "ts:") + (expect (org-ql--query-string-to-sexp "ts:") :to-equal '(ts)) - (expect (org-ql--plain-query "clocked:") + (expect (org-ql--query-string-to-sexp "clocked:") :to-equal '(clocked))) (it "To-do predicates" - (expect (org-ql--plain-query "todo:") + (expect (org-ql--query-string-to-sexp "todo:") :to-equal '(todo)) - (expect (org-ql--plain-query "todo:TODO") + (expect (org-ql--query-string-to-sexp "todo:TODO") :to-equal '(todo "TODO")) - (expect (org-ql--plain-query "todo:TODO,SOMEDAY") + (expect (org-ql--query-string-to-sexp "todo:TODO,SOMEDAY") :to-equal '(todo "TODO" "SOMEDAY"))) (it "Compound queries" - (expect (org-ql--plain-query "todo:SOMEDAY ts-a:from=2020-01-01,to=2021-01-01") + (expect (org-ql--query-string-to-sexp "todo:SOMEDAY ts-a:from=2020-01-01,to=2021-01-01") :to-equal '(and (todo "SOMEDAY") (ts-a :from "2020-01-01" :to "2021-01-01"))) - (expect (org-ql--plain-query "regexp:\"quoted phrase\" todo:SOMEDAY") + (expect (org-ql--query-string-to-sexp "regexp:\"quoted phrase\" todo:SOMEDAY") :to-equal '(and (regexp "quoted phrase") (todo "SOMEDAY"))))) (describe "Convert sexp queries to non-sexp queries" @@ -842,9 +856,9 @@ RESULTS should be a list of strings as returned by (org-ql-expect ('(scheduled :to today)) '("Skype with president of Antarctica" "Practice leaping tall buildings in a single bound" "Order a pizza" "Get haircut" "Fix flux capacitor" "Shop for groceries" "Rewrite Emacs in Common Lisp"))))) - ;; TODO: Test (src) predicate. That will require modifying test data, which will be a - ;; significant hassle. Manual testing shows that the predicate appears to work properly. - + ;; ;; TODO: Test (src) predicate. That will require modifying test data, which will be a + ;; ;; significant hassle. Manual testing shows that the predicate appears to work properly. + ;; (describe "(todo)" (org-ql-it "without arguments" From a2acf93a2c4fdcfd4752aa3c71d946b882ad8a09 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 01:33:14 -0600 Subject: [PATCH 262/560] Docs: (defpred.org) Fix example --- examples/defpred.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/defpred.org b/examples/defpred.org index 86565cf..75c28b7 100644 --- a/examples/defpred.org +++ b/examples/defpred.org @@ -164,7 +164,7 @@ Can we do that? In fact, we can, by using a query normalizer. Normalizers are collect `(property "person" ,name))))) :body (cl-loop for name in names thereis (or (property "person" name) - (tags (concat "person" name))))) + (tags name)))) #+END_SRC Now, don't faint from all the backquoting and unquoting--it's just Lisp, nothing to be afraid of! Let's slow down a moment and see what the normalized query looks like to be sure we're doing it correctly: From 485bbdfda8723722fbd2b39fe15a852ef5a99703 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 02:03:48 -0600 Subject: [PATCH 263/560] Meta: Upgrade makem.sh, Makefile, test.yml --- .github/workflows/test.yml | 2 +- Makefile | 2 +- makem.sh | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0b274ed..d5ec8cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,7 @@ # * test.yml --- Test Emacs packages using makem.sh on GitHub Actions # URL: https://github.com/alphapapa/makem.sh -# Version: 0.2 +# Version: 0.2.1 # * Commentary: diff --git a/Makefile b/Makefile index 68906e9..4abfce9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # * makem.sh/Makefile --- Script to aid building and testing Emacs Lisp packages # URL: https://github.com/alphapapa/makem.sh -# Version: 0.2 +# Version: 0.2.1 # * Arguments diff --git a/makem.sh b/makem.sh index 2d710a3..0cc3cbc 100755 --- a/makem.sh +++ b/makem.sh @@ -3,7 +3,7 @@ # * makem.sh --- Script to aid building and testing Emacs Lisp packages # URL: https://github.com/alphapapa/makem.sh -# Version: 0.2 +# Version: 0.2.1 # * Commentary: @@ -422,8 +422,9 @@ function package-main-file { function dependencies { # Echo list of package dependencies. - # Search package headers. - egrep -i '^;; Package-Requires: ' $(files-project-feature) $(files-project-test) \ + # Search package headers. Use -a so grep won't think that an Elisp file containing + # control characters (rare, but sometimes necessary) is binary and refuse to search it. + egrep -a -i '^;; Package-Requires: ' $(files-project-feature) $(files-project-test) \ | egrep -o '\([^([:space:]][^)]*\)' \ | egrep -o '^[^[:space:])]+' \ | sed -r 's/\(//g' \ From a24de862ec848568ffae1ed3fb2d515dca0dc6b1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 02:03:58 -0600 Subject: [PATCH 264/560] Fix: (org-ql-defpred) Use alist-get Until map-2.1 can automatically be installed with makem.sh... --- org-ql.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index b4b98b3..499e0b1 100644 --- a/org-ql.el +++ b/org-ql.el @@ -990,7 +990,8 @@ It would be expanded to: `(progn (cl-eval-when (compile load eval) (cl-defun ,fn-name ,args ,docstring ,body)) - (setf (map-elt org-ql-predicates ',predicate-name) + ;; SOMEDAY: Use `map-elt' here, after map 2.1 can be automatically installed in CI sandbox... + (setf (alist-get ',predicate-name org-ql-predicates) `(:name ,',name :aliases ,',aliases :fn ,',fn-name :docstring ,,docstring :args ,',args :normalizers ,',normalizers :preambles ,',preambles)) (unless org-ql-defpred-defer From 58bf5dc0a38050df6fc9494334a602181743b0bc Mon Sep 17 00:00:00 2001 From: "Zen Monk Alain M. Lafon" Date: Mon, 23 Nov 2020 09:33:44 +0100 Subject: [PATCH 265/560] Proofread `defpred` tutorial --- examples/defpred.org | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/defpred.org b/examples/defpred.org index 75c28b7..d5fc7c5 100644 --- a/examples/defpred.org +++ b/examples/defpred.org @@ -3,7 +3,7 @@ [2020-11-22 Sun 22:35] Imagine you have weekly meetings with other people, and during the week you take notes about items to discuss at each meeting. When the time for a meeting comes, you want to quickly and easily search for all of the items to discuss at the meeting. -You've been experimenting with different ways to track such data in Org. You've tried using tags, but some of the names in question conflict with other tags in your data (e.g. someone's named Charles, but you also work with a firm named Charles, Inc., and you'd prefer to continue using the tag =Charles= for entries about that firm), so you've been using tags like ~:personNAME:~, which seems awkward. You've tried using a ~:person: NAME~ property on entries, which has the advantage of not cluttering the tags list, but also the disadvantage of not being readily visible in an outline. +You've been experimenting with different ways to track such data in Org. You've tried using tags, but some of the names in question conflict with other tags in your data (e.g. someone's named Charles, but you also work with a firm named Charles, Inc., and you'd prefer to continue using the tag =Charles= for entries about that firm), so you've been using tags like ~:personNAME:~, which seems awkward. You've tried using a ~:person: NAME~ property on entries, which has the advantage of not cluttering the tags list, but also the disadvantage of not being readily visible in an outline. So you haven't decided on a long-term solution, but the meetings aren't going to wait--you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged ~:personAlice:~) when you're meeting with her, and all of the entries about Bob (which have the property ~:person: Bob~) when you're meeting with him What do you do? @@ -51,7 +51,7 @@ Enter =org-ql= custom search predicates. Let's start simple, by defining a pred :body (property "person" name)) #+END_SRC -Now let's see what results we get for searching this file for entries about Bob: +Now, let's see what results we get for searching this file for entries about Bob: #+BEGIN_SRC elisp :results list :exports both :cache yes (org-ql-query :select '(org-get-heading :no-tags) @@ -77,7 +77,7 @@ Hmm, looks like we need to remind Bob to wash his mug and take some mints after #+END_EXAMPLE -Nothing? Oh, right, Alice's entries use the ~:personAlice:~ tag, so we'll also need to also search those kind of entries. Let's make the predicate do that too: +Nothing? Oh, right, Alice's entries use the ~:personAlice:~ tag, so we'll also need to search those kind of entries. Let's make the predicate do that, too: #+BEGIN_SRC elisp :results silent :exports code (org-ql-defpred person (name) From a06ea62521c2ebbb0cdafb78f83a01896414ce24 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 02:59:43 -0600 Subject: [PATCH 266/560] Docs: (defpred.org) Tidy --- examples/defpred.org | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/defpred.org b/examples/defpred.org index d5fc7c5..3cdf07f 100644 --- a/examples/defpred.org +++ b/examples/defpred.org @@ -204,7 +204,7 @@ But wait, that's not all! If you order now, we'll throw in non-sexp query synta (org-ql-search (current-buffer) "person:Alice,Bob") #+END_SRC -Don't believe me? Well, you see, queries in this syntax are automatically converted to the sexp syntax, like: +Don't believe me? Well, you see, queries in this syntax are converted to the sexp syntax, like: #+BEGIN_SRC elisp :results code :exports both :cache yes (org-ql--query-string-to-sexp "person:Alice,Bob") @@ -215,7 +215,7 @@ Don't believe me? Well, you see, queries in this syntax are automatically conve (person "Alice" "Bob") #+END_SRC -But that happens automatically when you use a search command like =org-ql-search=. If you have =org-ql= installed already, you could even click this link: [[org-ql-search:person:Alice,Bob][Alice or Bob]]. Which, in Org syntax, looks like: +And that happens automatically when you use a search command like =org-ql-search=. If you have =org-ql= installed already, you could even click this link: [[org-ql-search:person:Alice,Bob][Alice or Bob]]. Which, in Org syntax, looks like: #+BEGIN_SRC org [[org-ql-search:person:Alice,Bob]] @@ -286,8 +286,8 @@ Finally, if you're a Lisper who appreciates anaphora, you might prefer a more sy :normalizers ((`(,predicate-names . ,names) `(or (tags ,@(--map `(concat "person" ,it) names)) ,@(--map `(property "person" ,it) names)))) - :body (--any (or (property "person" name) - (tags (concat "person" name))) + :body (--any (or (property "person" it) + (tags (concat "person" it))) names)) #+END_SRC From b01106bd0f73c5eaea55a8d41a6943977363f356 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 03:10:10 -0600 Subject: [PATCH 267/560] Docs: (defpred.org) Formless, conclusion --- examples/defpred.org | 47 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/examples/defpred.org b/examples/defpred.org index 3cdf07f..53dac32 100644 --- a/examples/defpred.org +++ b/examples/defpred.org @@ -5,7 +5,7 @@ You've been experimenting with different ways to track such data in Org. You've tried using tags, but some of the names in question conflict with other tags in your data (e.g. someone's named Charles, but you also work with a firm named Charles, Inc., and you'd prefer to continue using the tag =Charles= for entries about that firm), so you've been using tags like ~:personNAME:~, which seems awkward. You've tried using a ~:person: NAME~ property on entries, which has the advantage of not cluttering the tags list, but also the disadvantage of not being readily visible in an outline. -So you haven't decided on a long-term solution, but the meetings aren't going to wait--you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged ~:personAlice:~) when you're meeting with her, and all of the entries about Bob (which have the property ~:person: Bob~) when you're meeting with him What do you do? +So you haven't decided on a long-term solution, but the meetings aren't going to wait--you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged ~:personAlice:~) when you're meeting with her, and all of the entries about Bob (which have the property ~:person: Bob~) when you're meeting with him. What do you do? * Contents :PROPERTIES: @@ -19,6 +19,8 @@ So you haven't decided on a long-term solution, but the meetings aren't going to - [[#non-sexp-query-syntax][Non-sexp query syntax]] - [[#using-multiple-predicates][Using multiple predicates]] - [[#predicate-aliases][Predicate aliases]] +- [[#be-formless][Be formless]] +- [[#conclusion][Conclusion]] - [[#appendix-anaphoric-macros][Appendix: Anaphoric macros]] :END: @@ -276,6 +278,42 @@ And, you know what, if you're just so busy that you don't even have time to type (It's up to you to remember whether =p= means =person= or =priority=, but code can't solve everything.) +* Be formless + +We can even go a step further: since the normalizer rewrites the query to call the =property= and =tags= predicates instead, this =person= predicate doesn't even need a body form! + +#+BEGIN_SRC elisp :results silent :exports code + (org-ql-defpred (person p) (&rest names) + "Search for entries about any of NAMES." + :normalizers ((`(,predicate-names . ,names) + `(or (tags ,@(cl-loop for name in names + collect (concat "person" name))) + ,@(cl-loop for name in names + collect `(property "person" ,name)))))) +#+END_SRC + +Will it still work? + +#+BEGIN_SRC elisp :results list :exports both :cache yes + (org-ql-query :select '(org-get-heading :no-tags) + :from (current-buffer) + :where '(person "Alice" "Bob")) +#+END_SRC + +#+RESULTS[4f5971c56616f01d8d3c28a66ef380495ee3e158]: +- [#A] Loud pet parakeet +- [#C] Missing sticky notes +- [#C] Dirty dishes in sink +- [#A] Stinky coffee breath + +It does! + +* Conclusion + +In this tutorial, we've gone from having to write lengthy, complex query expressions for accommodating idiosyncratic requirements, to being able to write simple query expressions that abstract away ugly details, to rewriting those query expressions into a more optimal form before a search is even run. The end result is an Org Query Language that is customized to meet your specific needs. + +What new custom predicates will you write next? + * Appendix: Anaphoric macros Finally, if you're a Lisper who appreciates anaphora, you might prefer a more syntactically concise definition of the predicate using Dash macros: @@ -285,10 +323,7 @@ Finally, if you're a Lisper who appreciates anaphora, you might prefer a more sy "Search for entries about any of NAMES." :normalizers ((`(,predicate-names . ,names) `(or (tags ,@(--map `(concat "person" ,it) names)) - ,@(--map `(property "person" ,it) names)))) - :body (--any (or (property "person" it) - (tags (concat "person" it))) - names)) + ,@(--map `(property "person" ,it) names))))) #+END_SRC Let's make sure it works: @@ -305,7 +340,7 @@ Let's make sure it works: - [#C] Dirty dishes in sink - [#A] Stinky coffee breath -Have fun making custom search predicates! +Lisp is fun! * Example data :PROPERTIES: From 92d099caf61c87a712117fffee618485885679eb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 23 Nov 2020 03:19:13 -0600 Subject: [PATCH 268/560] Docs: (defpred.org) Add HTML export It looks nice, even if it isn't practically viewable on GitHub. --- examples/defpred.html | 766 ++++++++++++++++++ examples/defpred.org | 13 +- .../export/setup/theme-darksun-local.setup | 17 + examples/export/setup/theme-darksun.setup | 15 + .../export/styles/darksun/css/darksun.css | 264 ++++++ .../export/styles/darksun/css/hideshow.css | 110 +++ .../export/styles/darksun/css/htmlize.css | 145 ++++ .../export/styles/darksun/images/checked.png | Bin 0 -> 3136 bytes .../export/styles/darksun/images/fixme.png | Bin 0 -> 625 bytes .../styles/darksun/images/halfchecked.png | Bin 0 -> 3080 bytes .../export/styles/darksun/images/info.png | Bin 0 -> 4403 bytes .../export/styles/darksun/images/note.png | Bin 0 -> 4567 bytes examples/export/styles/darksun/images/tip.png | Bin 0 -> 4447 bytes .../styles/darksun/images/unchecked.png | Bin 0 -> 3087 bytes .../export/styles/darksun/images/warning.png | Bin 0 -> 4340 bytes examples/export/styles/darksun/js/darksun.js | 524 ++++++++++++ examples/export/styles/darksun/js/hideshow.js | 335 ++++++++ .../styles/darksun/js/jquery-1.11.0.min.js | 4 + .../styles/darksun/js/jquery-1.9.1.min.js | 5 + .../styles/darksun/js/jquery-ui-1.10.2.min.js | 12 + .../darksun/js/jquery.localscroll-min.js | 9 + .../darksun/js/jquery.scrollTo-1.4.3.1-min.js | 7 + .../styles/darksun/js/jquery.zclip.min.js | 12 + .../lib/js/jquery.stickytableheaders.min.js | 1 + .../lib/js/stickytableheaders-license.txt | 20 + 25 files changed, 2257 insertions(+), 2 deletions(-) create mode 100644 examples/defpred.html create mode 100644 examples/export/setup/theme-darksun-local.setup create mode 100644 examples/export/setup/theme-darksun.setup create mode 100644 examples/export/styles/darksun/css/darksun.css create mode 100644 examples/export/styles/darksun/css/hideshow.css create mode 100644 examples/export/styles/darksun/css/htmlize.css create mode 100644 examples/export/styles/darksun/images/checked.png create mode 100644 examples/export/styles/darksun/images/fixme.png create mode 100644 examples/export/styles/darksun/images/halfchecked.png create mode 100644 examples/export/styles/darksun/images/info.png create mode 100644 examples/export/styles/darksun/images/note.png create mode 100644 examples/export/styles/darksun/images/tip.png create mode 100644 examples/export/styles/darksun/images/unchecked.png create mode 100644 examples/export/styles/darksun/images/warning.png create mode 100644 examples/export/styles/darksun/js/darksun.js create mode 100644 examples/export/styles/darksun/js/hideshow.js create mode 100644 examples/export/styles/darksun/js/jquery-1.11.0.min.js create mode 100644 examples/export/styles/darksun/js/jquery-1.9.1.min.js create mode 100644 examples/export/styles/darksun/js/jquery-ui-1.10.2.min.js create mode 100644 examples/export/styles/darksun/js/jquery.localscroll-min.js create mode 100644 examples/export/styles/darksun/js/jquery.scrollTo-1.4.3.1-min.js create mode 100644 examples/export/styles/darksun/js/jquery.zclip.min.js create mode 100644 examples/export/styles/lib/js/jquery.stickytableheaders.min.js create mode 100644 examples/export/styles/lib/js/stickytableheaders-license.txt diff --git a/examples/defpred.html b/examples/defpred.html new file mode 100644 index 0000000..9c9b57e --- /dev/null +++ b/examples/defpred.html @@ -0,0 +1,766 @@ + + + + + + + +Org QL Custom Predicates Tutorial + + + + + + + + + + + + + +

+

Org QL Custom Predicates Tutorial

+ +

+[2020-11-22 Sun 22:35] Imagine you have weekly meetings with other people, and during the week you take notes about items to discuss at each meeting. When the time for a meeting comes, you want to quickly and easily search for all of the items to discuss at the meeting. +

+ +

+You've been experimenting with different ways to track such data in Org. You've tried using tags, but some of the names in question conflict with other tags in your data (e.g. someone's named Charles, but you also work with a firm named Charles, Inc., and you'd prefer to continue using the tag Charles for entries about that firm), so you've been using tags like :personNAME:, which seems awkward. You've tried using a :person: NAME property on entries, which has the advantage of not cluttering the tags list, but also the disadvantage of not being readily visible in an outline. +

+ +

+So you haven't decided on a long-term solution, but the meetings aren't going to wait–you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged :personAlice:) when you're meeting with her, and all of the entries about Bob (which have the property :person: Bob) when you're meeting with him. What do you do? +

+ +
+

Using built-in predicates

+
+

+You could start by using built-in Org QL predicates to search your data. For example: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(or (tags "personAlice")
+                          (property "person" "Bob")))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+That was easy enough, but it's not very…semantic. You have to think about the implementation details: Alice uses tags, Bob uses properties, and what if Charlie uses both? It starts to feel complicated, and it's a lot to type out every time. Is there an easier way? +

+
+
+ +
+

A custom (person) predicate

+
+

+Enter org-ql custom search predicates. Let's start simple, by defining a predicate to search for just the :person: property, one person at a time. The predicate will take one argument, a person's name, and search for that property. It would look like this: +

+ +
+
(org-ql-defpred person (name)
+  "Search for entries with the \"person\" property being NAME."
+  :body (property "person" name))
+
+
+ +

+Now, let's see what results we get for searching this file for entries about Bob: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Bob"))
+
+
+ +
    +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+Hmm, looks like we need to remind Bob to wash his mug and take some mints after lunch. Now what do we need to discuss with Alice? +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice"))
+
+
+ +
+
+ +

+Nothing? Oh, right, Alice's entries use the :personAlice: tag, so we'll also need to search those kind of entries. Let's make the predicate do that, too: +

+ +
+
(org-ql-defpred person (name)
+  "Search for entries with the \"person\" property being NAME or having the tag \"personNAME\"."
+  :body (or (property "person" name)
+            (tags (concat "person" name))))
+
+
+ +

+How about now? +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice"))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
+ +

+Hmm, I thought we already told her to leave Polly at home. +

+
+
+ +
+

Searching for multiple people at once

+
+

+Oh, wait, this week is shortened due to holidays, so we're having a combined meeting. How do we search for entries about either of them? Well, this is the obvious solution: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(or (person "Alice")
+                          (person "Bob")))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+And that works fine. But it seems like a lot to type. Could we make the person predicate accept multiple names instead? +

+ +
+
(org-ql-defpred person (&rest names)
+  "Search for entries about any of NAMES."
+  :body (cl-loop for name in names
+                 thereis (or (property "person" name)
+                             (tags (concat "person" name)))))
+
+
+ +

+Now let's search again: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice" "Bob"))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+That was easy! +

+
+
+ +
+

Normalizing queries to rewrite arguments

+
+

+Now, all this is well and good if you don't have hundreds of thousands of Org entries in your files. But what if you do? All that concat'ing happening on every entry could add up, and the query might take a few seconds. What if we could do that stringing-along just once, before running the query? We want to turn our (person "Alice" "Bob") query into this, with the :personNAME: strings already made and the per-person (property ...) predicates also included: +

+ +
+
(or (tags "personAlice" "personBob")
+    (property "person" "Alice")
+    (property "person" "Bob"))
+
+
+ +

+Can we do that? In fact, we can, by using a query normalizer. Normalizers are pcase forms (I know) that normalize query expressions before execution. We can use one to rewrite the query ahead of time, like this: +

+ +
+
(org-ql-defpred person (&rest names)
+  "Search for entries about any of NAMES."
+  :normalizers ((`(person . ,names)
+                 `(or (tags ,@(cl-loop for name in names
+                                       collect (concat "person" name)))
+                      ,@(cl-loop for name in names
+                                 collect `(property "person" ,name)))))
+  :body (cl-loop for name in names
+                 thereis (or (property "person" name)
+                             (tags name))))
+
+
+ +

+Now, don't faint from all the backquoting and unquoting–it's just Lisp, nothing to be afraid of! Let's slow down a moment and see what the normalized query looks like to be sure we're doing it correctly: +

+ +
+
(org-ql--normalize-query '(person "Alice" "Bob"))
+
+
+ +
+
(or (tags "personAlice" "personBob")
+    (property "person" "Alice")
+    (property "person" "Bob"))
+
+
+ +

+And, as they say, Bob's your uncle! Or even if he isn't, let's see if it works: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice" "Bob"))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+Yep, same result as the non-normalized query. And look at how much simpler it is to write (person "Alice" "Bob") than to write (or (tags "personAlice" "personBob") (property "person" "Alice") (property "person" "Bob")). +

+
+
+ +
+

Non-sexp query syntax

+
+

+But wait, that's not all! If you order now, we'll throw in non-sexp query syntax for free! That's right, your search could be as simple as typing person:Alice,Bob! +

+ +
+
(org-ql-search (current-buffer) "person:Alice,Bob")
+
+
+ +

+Don't believe me? Well, you see, queries in this syntax are converted to the sexp syntax, like: +

+ +
+
(org-ql--query-string-to-sexp "person:Alice,Bob")
+
+
+ +
+
(person "Alice" "Bob")
+
+
+ +

+And that happens automatically when you use a search command like org-ql-search. If you have org-ql installed already, you could even click this link: Alice or Bob. Which, in Org syntax, looks like: +

+ + + +

+And that would open an Agenda Mode buffer that looks like this: +

+ +
+Query: (person "Alice" "Bob")  In:meetings.org
+  [#A] Loud pet parakeet                                           :personAlice:
+  [#C] Missing sticky notes                                        :personAlice:
+  [#C] Dirty dishes in sink                                        :personAlice:
+  [#A] Stinky coffee breath
+
+
+
+ +
+

Using multiple predicates

+
+

+Oops, you forgot that there's a birthday party in 20 minutes, so you only have time to talk about the highest priority items at this joint meeting today. +

+ +

+No problem, let's just select high-priority items: +

+ +
+
(org-ql-search (current-buffer) "person:Alice,Bob priority:A")
+
+
+ +

+Which shows: +

+ +
+Query: (and (person "Alice" "Bob") (priority "A"))  In:meetings.org
+  [#A] Loud pet parakeet                                           :personAlice:
+  [#A] Stinky coffee breath
+
+
+
+ +
+

Predicate aliases

+
+

+And, you know what, if you're just so busy that you don't even have time to type the word person, you can add an abbreviated alias, p, like this: +

+ +
+
(org-ql-defpred (person p) (&rest names)
+  "Search for entries about any of NAMES."
+  :normalizers ((`(,predicate-names . ,names)
+                 `(or (tags ,@(cl-loop for name in names
+                                       collect (concat "person" name)))
+                      ,@(cl-loop for name in names
+                                 collect `(property "person" ,name)))))
+  :body (cl-loop for name in names
+                 thereis (or (property "person" name)
+                             (tags (concat "person" name)))))
+
+
+ +

+Let's try it: +

+ +
+
(org-ql-search (current-buffer) "p:Alice,Bob priority:A")
+
+
+ +

+And that shows: +

+ +
+Query: (and (person "Alice" "Bob") (priority "A"))  In:meetings.org
+  [#A] Loud pet parakeet                                           :personAlice:
+  [#A] Stinky coffee breath
+
+ +

+(It's up to you to remember whether p means person or priority, but code can't solve everything.) +

+
+
+ +
+

Be formless

+
+

+We can even go a step further: since the normalizer rewrites the query to call the property and tags predicates instead, this person predicate doesn't even need a body form! +

+ +
+
(org-ql-defpred (person p) (&rest names)
+  "Search for entries about any of NAMES."
+  :normalizers ((`(,predicate-names . ,names)
+                 `(or (tags ,@(cl-loop for name in names
+                                       collect (concat "person" name)))
+                      ,@(cl-loop for name in names
+                                 collect `(property "person" ,name))))))
+
+
+ +

+Will it still work? +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice" "Bob"))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+It does! +

+
+
+ +
+

Conclusion

+
+

+In this tutorial, we've gone from having to write lengthy, complex query expressions for accommodating idiosyncratic requirements, to being able to write simple query expressions that abstract away ugly details, to rewriting those query expressions into a more optimal form before a search is even run. The end result is an Org Query Language that is customized to meet your specific needs. +

+ +

+What new custom predicates will you write next? +

+
+
+ +
+

Appendix: Anaphoric macros

+
+

+Finally, if you're a Lisper who appreciates anaphora, you might prefer a more syntactically concise definition of the predicate using Dash macros: +

+ +
+
(org-ql-defpred (person p) (&rest names)
+  "Search for entries about any of NAMES."
+  :normalizers ((`(,predicate-names . ,names)
+                 `(or (tags ,@(--map `(concat "person" ,it) names))
+                      ,@(--map `(property "person" ,it) names)))))
+
+
+ +

+Let's make sure it works: +

+ +
+
(org-ql-query :select '(org-get-heading :no-tags)
+              :from (current-buffer)
+              :where '(person "Alice" "Bob"))
+
+
+ +
    +
  • [#A] Loud pet parakeet
  • +
  • [#C] Missing sticky notes
  • +
  • [#C] Dirty dishes in sink
  • +
  • [#A] Stinky coffee breath
  • +
+ +

+Lisp is fun! +

+
+
+ +
+

Example data

+
+
+ +
+

Loud pet parakeet   personAlice

+
+ +
+

Missing sticky notes   personAlice

+
+
+
+ +
+

Dirty dishes in sink   personAlice

+
+
+
+ +
+

Stinky coffee breath

+
+
+
+
+
+
+

Created: 2020-11-23 Mon 03:31

+

Validate

+
+ + diff --git a/examples/defpred.org b/examples/defpred.org index 53dac32..4f19576 100644 --- a/examples/defpred.org +++ b/examples/defpred.org @@ -1,5 +1,6 @@ #+TITLE: Org QL Custom Predicates Tutorial -#+OPTIONS: author:nil creator:nil created:nil date:nil num:nil title:t +#+OPTIONS: author:nil creator:nil created:nil date:nil num:nil title:t broken-links:t +#+SETUPFILE: export/setup/theme-darksun-local.setup [2020-11-22 Sun 22:35] Imagine you have weekly meetings with other people, and during the week you take notes about items to discuss at each meeting. When the time for a meeting comes, you want to quickly and easily search for all of the items to discuss at the meeting. @@ -7,7 +8,7 @@ You've been experimenting with different ways to track such data in Org. You've So you haven't decided on a long-term solution, but the meetings aren't going to wait--you need to search that data now, and you have a mix of both tags and properties in your entries. What you need is to be able to search for all of the entries about Alice (which you've tagged ~:personAlice:~) when you're meeting with her, and all of the entries about Bob (which have the property ~:person: Bob~) when you're meeting with him. What do you do? -* Contents +* Contents :noexport: :PROPERTIES: :TOC: :include siblings :ignore this :END: @@ -130,6 +131,8 @@ And that works fine. But it seems like a lot to type. Could we make the =perso (tags (concat "person" name))))) #+END_SRC +Now let's search again: + #+BEGIN_SRC elisp :results list :exports both :cache yes (org-ql-query :select '(org-get-heading :no-tags) :from (current-buffer) @@ -243,6 +246,8 @@ No problem, let's just select high-priority items: (org-ql-search (current-buffer) "person:Alice,Bob priority:A") #+END_SRC +Which shows: + #+BEGIN_EXAMPLE Query: (and (person "Alice" "Bob") (priority "A")) In:meetings.org [#A] Loud pet parakeet :personAlice: @@ -266,10 +271,14 @@ And, you know what, if you're just so busy that you don't even have time to type (tags (concat "person" name))))) #+END_SRC +Let's try it: + #+BEGIN_SRC elisp :results silent :exports code (org-ql-search (current-buffer) "p:Alice,Bob priority:A") #+END_SRC +And that shows: + #+BEGIN_EXAMPLE Query: (and (person "Alice" "Bob") (priority "A")) In:meetings.org [#A] Loud pet parakeet :personAlice: diff --git a/examples/export/setup/theme-darksun-local.setup b/examples/export/setup/theme-darksun-local.setup new file mode 100644 index 0000000..1ae015b --- /dev/null +++ b/examples/export/setup/theme-darksun-local.setup @@ -0,0 +1,17 @@ +# -*- mode: org; -*- + +# The files that hide sections and display a navbar and ToC are commented out. + +# #+HTML_HEAD: +#+HTML_HEAD: +# #+HTML_HEAD: + +#+HTML_HEAD: +#+HTML_HEAD: + +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +# #+HTML_HEAD: +#+HTML_HEAD: diff --git a/examples/export/setup/theme-darksun.setup b/examples/export/setup/theme-darksun.setup new file mode 100644 index 0000000..a5abe0e --- /dev/null +++ b/examples/export/setup/theme-darksun.setup @@ -0,0 +1,15 @@ +# -*- mode: org; -*- + +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: + +#+HTML_HEAD: +#+HTML_HEAD: + +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: +#+HTML_HEAD: diff --git a/examples/export/styles/darksun/css/darksun.css b/examples/export/styles/darksun/css/darksun.css new file mode 100644 index 0000000..212fb9a --- /dev/null +++ b/examples/export/styles/darksun/css/darksun.css @@ -0,0 +1,264 @@ +* { + border-color: #657b83; +} +a { + color: #268bd2 !important; +} +a:visited { + color: #6c71c4 !important; +} +body { + background-color: #002b36 !important; + color: #839496 !important; + font-family: Libre Baskerville, serif; +} +html { + background-color: #002b36 !important; +} +input, +textarea { + background-color: #073642 !important; + color: #839496 !important; +} +blockquote, +code, +pre { + background-color: #073642 !important; + border: 1px solid #094352 !important; + border-radius: 2px; + box-shadow: none; + color: #839496 !important; +} +code { + font-size: 1.2em; +} +img { + margin: 0.5em; +} +.buttons { + background-color: #073642 !important; + color: #93a1a1 !important; + font-family: sans-serif; + font-size: 1.5rem; +} +.hsReviewPanel { + display: none; +} +.title { + border: 0; +} +#postamble { + display: none; +} +#banner { + text-align: center; +} +#tabs { + background-color: #073642 !important; + float: left; + margin: 0px 0px 20px 0px; + padding: 0; + width: 100%; + font-family: sans-serif; +} +#tabs ul { + margin: 0; + padding: 0; +} +#tabs li { + float: left; + list-style-type: none; + margin: 0px 2px 0px 0px; + padding: 0px 0px 0px 0px; + white-space: nowrap; +} +#tabs li a { + display: block; + font-size: 120%; + font-weight: bold; + margin: 0; + padding: 4px 10px 4px 10px; + text-decoration: none; +} +#tabs li a:hover { + color: #90c5eb !important; +} +#tabs li.ui-tabs-active a { + background-color: #094352 !important; + color: #59a9e1 !important; +} +#content { + clear: both; + width: 80%; +} +#content > p { + margin: 1em; +} +#content > div > h2 { + margin: 0.25rem; +} +#postamble { + text-align: right; +} +blockquote { + background-color: #073642 !important; + padding-left: 0.75em; + padding-right: 0.75em; + padding-top: 0.01em; + padding-bottom: 0.01em; + overflow: hidden; + margin-left: 0; +} +.outline-text-2, +.outline-text-3, +.outline-text-4, +.outline-text-5, +.outline-text-6 { + padding-left: 4%; +} +.outline-3 { + padding-left: 4%; +} +.outline-4 { + padding-left: 4%; +} +.outline-5 { + padding-left: 4%; +} +.outline-6 { + padding-left: 4%; +} +h1, +h2, +h3, +h4, +h5, +h6 { + font-family: sans-serif; + border-bottom: 2px solid; + border-color: #094352 !important; +} +a:hover { + text-decoration: underline; +} +#search { + display: block; + float: right; +} +.tag { + background-color: #002b36 !important; + color: #93a1a1 !important; + border: 0px; +} +.tag span { + background-color: #094352 !important; + margin: 0.25em; + padding: 0.25em; +} +#table-of-contents { + display: table; + float: right; +} +#table-of-contents h2 { + display: none; +} +#table-of-contents li { + list-style-type: none; +} +#table-of-contents a:hover { + text-decoration: underline; +} +#minitoc { + background-color: #073642 !important; + position: fixed; + top: 0px; + right: -5px; + padding: 0.5em; + z-index: 200; + width: 18%; + word-wrap: normal; + overflow: hidden; +} +#minitoc ul { + margin: 0.5em; + padding-left: 1em; +} +#minitoc h2 { + margin-top: 0; + margin-bottom: 0; + font-size: 110%; +} +#minitoc a { + display: block; + font-family: sans-serif; + text-decoration: none; +} +#minitoc a:hover { + text-decoration: underline; +} +/* #minitoc a { */ +/* display: none; */ +/* } */ +#minitoc:hover a { + display: block; +} +#toTop { + top: -100px; + position: fixed; + text-align: center; + z-index: 999; + display: none; +} +#toTop:hover { + text-decoration: underline; +} +#left-panel-wrapper { + display: none; + position: fixed; + z-index: 200; +} +#left-panel-contents { + display: none; + position: fixed; + text-align: left; + top: 0; + z-index: 200; +} +#left-panel-button { + transform: rotate(90deg); + left: -23px; + position: fixed; + top: 50%; + z-index: 200; +} +#right-panel-wrapper { + position: fixed; + z-index: 200; +} +#right-panel-contents { + display: none; + z-index: 200; + position: fixed; + text-align: left; + top: 0; +} +.snippet-copy-to-clipboard { + display: none; + position: absolute; + left: 50px; + top: 50px; +} +.org-ol > li, +.org-dl > dt { + margin-top: 0.5em; +} +.org-ul { + margin-top: 1em; + margin-bottom: 1em; +} +.org-ul li { + margin-top: 0.5em; +} +.org-ul > li > a { + font-family: sans-serif; +} diff --git a/examples/export/styles/darksun/css/hideshow.css b/examples/export/styles/darksun/css/hideshow.css new file mode 100644 index 0000000..4ded9b5 --- /dev/null +++ b/examples/export/styles/darksun/css/hideshow.css @@ -0,0 +1,110 @@ +/* hideshow.css --- HideShow CSS file */ + +/* Copyright (C) 2014 All Right Reserved, Fabrice Niessen */ + +/* This file is free software: you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License as */ +/* published by the Free Software Foundation, either version 3 of */ +/* the License, or (at your option) any later version. */ + +/* This file is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ + +/* Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")> */ +/* URL: https://github.com/fniessen/hide-show/ */ +/* Version: 20140912.1722 */ + +.hsExpanded.hsAnchor {background: #EE7700;} + +.buttons { + padding: 0px 7px 13px 0px; + background: #0A3F69; +} + +.hsButton { + color: white; + float: right; + font-size: 70%; + margin-left: 10px; +} + + .hsButton:hover { + text-decoration: underline; + cursor: pointer; + } + +.ellipsis { + color: #999999; + /* background-color: #FFF8C0; */ + /* float: right; */ + margin-left: 0.6em; +} + +.hsReview { + border: 1px solid #A4A4A4; + background-color: white; + z-index: 500; /* must be greater then z-index of hsOverlay */ + position: relative; /* required for z-index to work */ +} + +#hsOverlay { + width: 100%; + height: 100%; + position: fixed; + left: 0px; + top: 0px; + background-color: #000; + opacity: .70; + z-index: 250; /* must be greater than any other z-index (except the one for .hsReview */ +} + +.hsReviewPanel { + background-color: #757176; + color: white; + line-height: 1.1em; + margin: 10px 0px; + padding: 10px; + position: fixed; + width: auto; + bottom: 0px; + right: 0px; + z-index: 501; + text-align: center; +} + + .hsReviewPanel.hsReviewing { + display: none; + } + + .hsReviewPanel:hover { + cursor: pointer; + } + +.hsReviewingPanel { + background-color: white; + color: #757176; + line-height: 1.1em; + margin: 10px 0px; + padding: 10px; + position: fixed; + width: auto; + bottom: 0px; + right: 0px; + z-index: 501; + text-align: center; +} + +.hsReviewButton:hover { + cursor: pointer; +} + +.hsUnselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} diff --git a/examples/export/styles/darksun/css/htmlize.css b/examples/export/styles/darksun/css/htmlize.css new file mode 100644 index 0000000..f08e781 --- /dev/null +++ b/examples/export/styles/darksun/css/htmlize.css @@ -0,0 +1,145 @@ +.org-bold { /* bold */ font-weight: bold; } +.org-bold-italic { /* bold-italic */ font-weight: bold; font-style: italic; } +.org-buffer-menu-buffer { /* buffer-menu-buffer */ font-weight: bold; } +.org-builtin { /* font-lock-builtin-face */ color: #7a378b; } +.org-button { /* button */ text-decoration: underline; } +.org-calendar-today { /* calendar-today */ text-decoration: underline; } +.org-change-log-acknowledgement { /* change-log-acknowledgement */ color: #b22222; } +.org-change-log-conditionals { /* change-log-conditionals */ color: #a0522d; } +.org-change-log-date { /* change-log-date */ color: #8b2252; } +.org-change-log-email { /* change-log-email */ color: #a0522d; } +.org-change-log-file { /* change-log-file */ color: #0000ff; } +.org-change-log-function { /* change-log-function */ color: #a0522d; } +.org-change-log-list { /* change-log-list */ color: #a020f0; } +.org-change-log-name { /* change-log-name */ color: #008b8b; } +.org-comint-highlight-input { /* comint-highlight-input */ font-weight: bold; } +.org-comint-highlight-prompt { /* comint-highlight-prompt */ color: #00008b; } +.org-comment { /* font-lock-comment-face */ color: #b22222; } +.org-comment-delimiter { /* font-lock-comment-delimiter-face */ color: #b22222; } +.org-completions-annotations { /* completions-annotations */ font-style: italic; } +.org-completions-common-part { /* completions-common-part */ color: #000000; background-color: #ffffff; } +.org-completions-first-difference { /* completions-first-difference */ font-weight: bold; } +.org-constant { /* font-lock-constant-face */ color: #008b8b; } +.org-diary { /* diary */ color: #ff0000; } +.org-diff-context { /* diff-context */ color: #7f7f7f; } +.org-diff-file-header { /* diff-file-header */ background-color: #b3b3b3; font-weight: bold; } +.org-diff-function { /* diff-function */ background-color: #cccccc; } +.org-diff-header { /* diff-header */ background-color: #cccccc; } +.org-diff-hunk-header { /* diff-hunk-header */ background-color: #cccccc; } +.org-diff-index { /* diff-index */ background-color: #b3b3b3; font-weight: bold; } +.org-diff-nonexistent { /* diff-nonexistent */ background-color: #b3b3b3; font-weight: bold; } +.org-diff-refine-change { /* diff-refine-change */ background-color: #d9d9d9; } +.org-dired-directory { /* dired-directory */ color: #0000ff; } +.org-dired-flagged { /* dired-flagged */ color: #ff0000; font-weight: bold; } +.org-dired-header { /* dired-header */ color: #228b22; } +.org-dired-ignored { /* dired-ignored */ color: #7f7f7f; } +.org-dired-mark { /* dired-mark */ color: #008b8b; } +.org-dired-marked { /* dired-marked */ color: #ff0000; font-weight: bold; } +.org-dired-perm-write { /* dired-perm-write */ color: #b22222; } +.org-dired-symlink { /* dired-symlink */ color: #a020f0; } +.org-dired-warning { /* dired-warning */ color: #ff0000; font-weight: bold; } +.org-doc { /* font-lock-doc-face */ color: #8b2252; } +.org-escape-glyph { /* escape-glyph */ color: #a52a2a; } +.org-file-name-shadow { /* file-name-shadow */ color: #7f7f7f; } +.org-flyspell-duplicate { /* flyspell-duplicate */ color: #cdad00; font-weight: bold; text-decoration: underline; } +.org-flyspell-incorrect { /* flyspell-incorrect */ color: #ff4500; font-weight: bold; text-decoration: underline; } +.org-fringe { /* fringe */ background-color: #f2f2f2; } +.org-function-name { /* font-lock-function-name-face */ color: #0000ff; } +.org-header-line { /* header-line */ color: #333333; background-color: #e5e5e5; } +.org-help-argument-name { /* help-argument-name */ font-style: italic; } +.org-highlight { /* highlight */ background-color: #b4eeb4; } +.org-holiday { /* holiday */ background-color: #ffc0cb; } +.org-isearch { /* isearch */ color: #b0e2ff; background-color: #cd00cd; } +.org-isearch-fail { /* isearch-fail */ background-color: #ffc1c1; } +.org-italic { /* italic */ font-style: italic; } +.org-keyword { /* font-lock-keyword-face */ color: #a020f0; } +.org-lazy-highlight { /* lazy-highlight */ background-color: #afeeee; } +.org-link { /* link */ color: #0000ff; text-decoration: underline; } +.org-link-visited { /* link-visited */ color: #8b008b; text-decoration: underline; } +.org-log-edit-header { /* log-edit-header */ color: #a020f0; } +.org-log-edit-summary { /* log-edit-summary */ color: #0000ff; } +.org-log-edit-unknown-header { /* log-edit-unknown-header */ color: #b22222; } +.org-match { /* match */ background-color: #ffff00; } +.org-next-error { /* next-error */ background-color: #eedc82; } +.org-nobreak-space { /* nobreak-space */ color: #a52a2a; text-decoration: underline; } +.org-org-archived { /* org-archived */ color: #7f7f7f; } +.org-org-block { /* org-block */ color: #7f7f7f; } +.org-org-block-begin-line { /* org-block-begin-line */ color: #b22222; } +.org-org-block-end-line { /* org-block-end-line */ color: #b22222; } +.org-org-checkbox { /* org-checkbox */ font-weight: bold; } +.org-org-checkbox-statistics-done { /* org-checkbox-statistics-done */ color: #228b22; font-weight: bold; } +.org-org-checkbox-statistics-todo { /* org-checkbox-statistics-todo */ color: #ff0000; font-weight: bold; } +.org-org-clock-overlay { /* org-clock-overlay */ background-color: #ffff00; } +.org-org-code { /* org-code */ color: #7f7f7f; } +.org-org-column { /* org-column */ background-color: #e5e5e5; } +.org-org-column-title { /* org-column-title */ background-color: #e5e5e5; font-weight: bold; text-decoration: underline; } +.org-org-date { /* org-date */ color: #a020f0; text-decoration: underline; } +.org-org-document-info { /* org-document-info */ color: #191970; } +.org-org-document-info-keyword { /* org-document-info-keyword */ color: #7f7f7f; } +.org-org-document-title { /* org-document-title */ color: #191970; font-size: 144%; font-weight: bold; } +.org-org-done { /* org-done */ color: #228b22; font-weight: bold; } +.org-org-drawer { /* org-drawer */ color: #0000ff; } +.org-org-ellipsis { /* org-ellipsis */ color: #b8860b; text-decoration: underline; } +.org-org-footnote { /* org-footnote */ color: #a020f0; text-decoration: underline; } +.org-org-formula { /* org-formula */ color: #b22222; } +.org-org-headline-done { /* org-headline-done */ color: #bc8f8f; } +.org-org-hide { /* org-hide */ color: #ffffff; } +.org-org-latex-and-export-specials { /* org-latex-and-export-specials */ color: #8b4513; } +.org-org-level-1 { /* org-level-1 */ color: #0000ff; } +.org-org-level-2 { /* org-level-2 */ color: #a0522d; } +.org-org-level-3 { /* org-level-3 */ color: #a020f0; } +.org-org-level-4 { /* org-level-4 */ color: #b22222; } +.org-org-level-5 { /* org-level-5 */ color: #228b22; } +.org-org-level-6 { /* org-level-6 */ color: #008b8b; } +.org-org-level-7 { /* org-level-7 */ color: #7a378b; } +.org-org-level-8 { /* org-level-8 */ color: #8b2252; } +.org-org-link { /* org-link */ color: #0000ff; text-decoration: underline; } +.org-org-meta-line { /* org-meta-line */ color: #b22222; } +.org-org-mode-line-clock { /* org-mode-line-clock */ color: #000000; background-color: #bfbfbf; } +.org-org-mode-line-clock-overrun { /* org-mode-line-clock-overrun */ color: #000000; background-color: #ff0000; } +.org-org-quote { /* org-quote */ color: #7f7f7f; } +.org-org-scheduled { /* org-scheduled */ color: #006400; } +.org-org-scheduled-previously { /* org-scheduled-previously */ color: #b22222; } +.org-org-scheduled-today { /* org-scheduled-today */ color: #006400; } +.org-org-sexp-date { /* org-sexp-date */ color: #a020f0; } +.org-org-special-keyword { /* org-special-keyword */ color: #a020f0; } +.org-org-table { /* org-table */ color: #0000ff; } +.org-org-tag { /* org-tag */ font-weight: bold; } +.org-org-target { /* org-target */ text-decoration: underline; } +.org-org-time-grid { /* org-time-grid */ color: #b8860b; } +.org-org-todo { /* org-todo */ color: #ff0000; font-weight: bold; } +.org-org-upcoming-deadline { /* org-upcoming-deadline */ color: #b22222; } +.org-org-verbatim { /* org-verbatim */ color: #7f7f7f; } +.org-org-verse { /* org-verse */ color: #7f7f7f; } +.org-org-warning { /* org-warning */ color: #ff0000; font-weight: bold; } +.org-outline-1 { /* outline-1 */ color: #0000ff; } +.org-outline-2 { /* outline-2 */ color: #a0522d; } +.org-outline-3 { /* outline-3 */ color: #a020f0; } +.org-outline-4 { /* outline-4 */ color: #b22222; } +.org-outline-5 { /* outline-5 */ color: #228b22; } +.org-outline-6 { /* outline-6 */ color: #008b8b; } +.org-outline-7 { /* outline-7 */ color: #7a378b; } +.org-outline-8 { /* outline-8 */ color: #8b2252; } +.org-preprocessor { /* font-lock-preprocessor-face */ color: #7a378b; } +.org-query-replace { /* query-replace */ color: #b0e2ff; background-color: #cd00cd; } +.org-regexp-grouping-backslash { /* font-lock-regexp-grouping-backslash */ font-weight: bold; } +.org-regexp-grouping-construct { /* font-lock-regexp-grouping-construct */ font-weight: bold; } +.org-region { /* region */ background-color: #eedc82; } +.org-secondary-selection { /* secondary-selection */ background-color: #ffff00; } +.org-shadow { /* shadow */ color: #7f7f7f; } +.org-show-paren-match { /* show-paren-match */ background-color: #40e0d0; } +.org-show-paren-mismatch { /* show-paren-mismatch */ color: #ffffff; background-color: #a020f0; } +.org-string { /* font-lock-string-face */ color: #8b2252; } +.org-tool-bar { /* tool-bar */ color: #000000; background-color: #bfbfbf; } +.org-tooltip { /* tooltip */ color: #000000; background-color: #ffffe0; } +.org-trailing-whitespace { /* trailing-whitespace */ background-color: #ff0000; } +.org-type { /* font-lock-type-face */ color: #228b22; } +.org-underline { /* underline */ text-decoration: underline; } +.org-variable-name { /* font-lock-variable-name-face */ color: #a0522d; } +.org-warning { /* font-lock-warning-face */ color: #ff0000; font-weight: bold; } +.org-widget-button { /* widget-button */ font-weight: bold; } +.org-widget-button-pressed { /* widget-button-pressed */ color: #ff0000; } +.org-widget-documentation { /* widget-documentation */ color: #006400; } +.org-widget-field { /* widget-field */ background-color: #d9d9d9; } +.org-widget-inactive { /* widget-inactive */ color: #7f7f7f; } +.org-widget-single-line-field { /* widget-single-line-field */ background-color: #d9d9d9; } diff --git a/examples/export/styles/darksun/images/checked.png b/examples/export/styles/darksun/images/checked.png new file mode 100644 index 0000000000000000000000000000000000000000..ebdc03bdaba59b81824d0b0f2ac115762310d2dc GIT binary patch literal 3136 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 -^9N* zU7@RT1Wj2P7#J9nyxm>oS$PHaGB7Z37I;J!Gca%qgD@k*tT_@43=DmqE{-7*ms9(1 z3pFe7xG+!Ly*6U)rKlhO&zrEw$nWAmGlz9jEW@M;GmO0$eVZ>Gvr6v`W8VCI;a!&Z zs~7*s$=|!^zg3Kl-Mpv<6LJ5IXY@HU^7T%4O}P6*&N_d$_XPXm&fs(f=IcwR{K(}I z%Y3nK>Z(%-DY2*diWh7(m9RV`)3aE9|Kq-Y;p?vYue@&0=)ILwxKZ%%R0akH)e_f; zl9a@fRIB8o)Wnih1|tJQBV7YST|?s#BO@y#GbIKU^w z_5c6>uCA`9P9FRBZOZ>oDgWM@Gcz+h-pHt~#Q6UO`-&+{|E@B)STOWgF{DK@w6wJR z|NlSrVR!}u0|R48kY6x^!?PP{AWo9Ey9+}HtE>kD1EZs-i(`nz>9tc{PCKl?(b_B; zbK=v#{M+0aeKU>i)2gbZg;_pzdT-8E`_;8gbI}*BgTH@;%v8Tr_;YIUGTp#B50(F+ zXJRrwtvQ}!V;vfrT+a zv&M`wHq6r&aGNN5Oi@*)z4ZHGqf?zu{;k`?j+?r6mVB0(ap^1b4ZkZ_p33m;*m7Oa z!r;P7hlHyl4#yAsiMvQ-tXasm(`%#o6+J^2Tbl&VvS8PW6Af_*AKsYEyuIm`!K|dZ z8IctNE5v%m4zGImn<<4^%QAnLZMKxEmJA>3{}~RoD;&0IzmeYaX`aKHg=PAN4ZGGi z?mhRXX}-L)e!=9{?+i)P4Q~gZ;@#u@J@#FBod|~#AIs8g*19E&QvZGD*m@~{&o}wF z${M+S-?mmV|9&Jl!B@raBm)D3YKdz^NlIc#s#S7PYGO$$gOP!uiLQa6u90Pkp{bRD zv6ZR0wt=CQfx)tgIq4`Ga`RI%(<)Ikm{^&ZSs55YG?dTkJI27kz~JfX=d#Wzp$PyX C+w#5u literal 0 HcmV?d00001 diff --git a/examples/export/styles/darksun/images/halfchecked.png b/examples/export/styles/darksun/images/halfchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..afd695e4145e06f388b207903aa87c474f47e957 GIT binary patch literal 3080 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�PV*|l=S%D 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 HDWM4fo4`&G literal 0 HcmV?d00001 diff --git a/examples/export/styles/darksun/images/note.png b/examples/export/styles/darksun/images/note.png new file mode 100644 index 0000000000000000000000000000000000000000..1c6b8eb0fb39720842be86b0343adfdcbf929982 GIT binary patch literal 4567 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}oCO|{#S9GG!XV7ZFl&wk z0|S?Trn7TEKt_H^esM;Afr6*AvqC{pep+TuDg#5st+~PJA;B-jY`@?8;^f`YFvUAR zNR&e%$f>(QWTKjuBBy{?hvLGUqJakmU0qqEPb}zQ?(1vl5e?Mg>EgP<{zP$6U-ROQ zu2a7sRxi%Jw&(k^v;VeUw|lQz`~GlIyvbvLx3(rf_nY4%M1;3f6T0AWQd-kD9X5C zB7=f(YKIF$hBd>Q^I=`C3=swlB5B@7EE#U-G8lMT#JFBV&*2Bohp{DjnN#sh3w(sdU6`)JjJy| z%o3RrXF2E{s+=il)M�PV*|l=S%D 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 literal 0 HcmV?d00001 diff --git a/examples/export/styles/darksun/images/tip.png b/examples/export/styles/darksun/images/tip.png new file mode 100644 index 0000000000000000000000000000000000000000..743ef89c3a48cb65d51f0efb7305be9f2beba401 GIT binary patch literal 4447 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}oCO|{#S9GG!XV7ZFl&wk z0|S?Trn7TEKt_H^esM;Afr6*AvqC{pep+TuDg#5st+~PJA;B-jY`@?8;^f`YFvUAR zNR&e%$f>(QWTKjuBBy{?hvLGUqJakmU0qqEPb}zQ?(1vl5e?Mg>EgP<{zP$6U-ROQ zu2a7sRxi%Jw&(k^v;VeUw|lQz`~GlIyvbvLx3(rf_nY4%M1;3f6T0AWQd-kD9X5C zB7=f(YKIF$hBd>Q^I=`C3=swlB5B@7EE#U-G8lMT#JFBV&*2Bohp{DjnN#sh3w(sdU6`)JjJy| z%o3RrXF2E{s+=il)M�PV*|l=S%D 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�PV*|l=S%D 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 u&mTHenjp4=ImNr`%Bt|qzdirUGc=^M&R_i6;(@ literal 0 HcmV?d00001 diff --git a/examples/export/styles/darksun/js/darksun.js b/examples/export/styles/darksun/js/darksun.js new file mode 100644 index 0000000..99ce23f --- /dev/null +++ b/examples/export/styles/darksun/js/darksun.js @@ -0,0 +1,524 @@ +// darksun.js --- darksun JS file +// +// Copyright (C) 2011-2016 All Right Reserved, Fabrice Niessen +// +// This file is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")> +// URL: https://github.com/fniessen/org-html-themes/ +// Version: 20140515.1841 + +$(function() { + $('p'). + html(function(index, old) { + return old.replace('FIXME', + 'FIXME'); + }); + $('p'). + html(function(index, old) { + return old.replace('XXX', + 'XXX'); + }); +}); + +// Remove leading section number +$(function() { + $('.section-number-2').text(""); + for (var i = 3; i <= 5; i++) { + $('.section-number-' + i).each(function() { + $(this).text($(this).text().replace(/^[0-9]+\./g, "")); + }); + } +}); + +$(function() { + $('
').prependTo('body'); +}); + +// generate contents of minitoc +function generateMiniToc(divId) { + $('#minitoc-content').empty().append('

In this section

    '); + $('#' + divId).find('h3').each(function(i) { + // [2018-09-03 Mon 03:48] Get text up to non-breaking space, + // to omit the tags. If there are no tags, there will be no + //  , so get all the text. (This fixes a bug in the + // original code.) + let text = null; + let pos = $(this).text().search(/ | ►/); + if (pos > 0) { + text = $(this).text().substring(0, pos); + } + else { + text = $(this).text(); + } + $("#minitoc-content>ul").append("
  • " + + text + "
  • "); + }); + // Ensure that the target is expanded (hideShow) + $('#minitoc-content a[href^="#"]').click(function() { + var href = $(this).attr('href'); + hsExpandAnchor(href); + }); +} + +// display tabs +function tabifySections() { + + // hide TOC (if present) + $('#table-of-contents').hide(); + + // grab the list of `h2' from the page + var allSections = []; + $('h2') + .each(function() { + // Remove TODO keywords and tags (contained in spans) + var tabText = $(this).clone().find('span').remove().end() + .text().trim(); + var tabId = $(this).parent().attr('id'); + if (tabText) { + // - remove heading number (all leading digits) + // - remove progress logging (between square brackets) + // - remove leading and trailing spaces + tabText = tabText.replace(/^\d+\s+/, '').replace(/\[[\d/%]+\]/, '').trim(); + + allSections.push({ + text: tabText, + id: tabId + }); + } + }); + + // create the tab links + var tabs = $('
      '); + for (i = 0; i < allSections.length; i++) { + var item = allSections[i]; + html = $('
    • ' + item.text + '
    • '); + tabs.append(html); + } + + // insert tabs menu after title (`h1'), or at the beginning of the content + if($('.title').length !== 0) { + $('.title').after(tabs); + } + else { + $('#content').prepend(tabs); + } +} + +function selectTabAndScroll(href) { + // At this point we assume that href is local (starts with #) + // alert(href); + + // Find the tab to activate + var targetTab = $(href).closest('.ui-tabs-panel'); + var targetTabId = targetTab.attr('id'); + var targetTabAriaLabel = targetTab.attr('aria-labelledby'); + + var targetTabIndex = $("#content ul li") + .index($('[aria-labelledby="' + targetTabAriaLabel + '"]')); + + // Activate target tab + $('#content').tabs('option', 'active', targetTabIndex); + + // Rebuild minitoc + generateMiniToc(targetTabId); + + // Set the location hash + // document.location.hash = href; + + // Scroll to top if href was a tab + if (href == '#' + targetTabId) { + // alert(targetTabId); + $.scrollTo(0); + } + // Scroll to href if href was not a tab + else { + $.scrollTo(href); + } +} + +$(document).ready(function() { + $('#preamble').remove(); + $('#table-of-contents').remove(); + + // Initialize hideShow + hsInit(); + + // Prepare for tabs + tabifySections(); + + // Build the tabs from the #content div + $('#content').tabs(); + + // Set default animation + $('#content').tabs('option', 'show', true); + + // Rebuild minitoc when a tab is activated + $('#content').tabs({ + activate: function(event, ui) { + var divId = ui.newTab.attr('aria-controls'); + generateMiniToc(divId); + } + }); + + // Required to get the link of the tab in URL + $('#content ul').localScroll({ + target: '#content', + duration: 0, + hash: true + }); + + // Handle hash in URL + if ($('#content') && document.location.hash) { + hsExpandAnchor(document.location.hash); + selectTabAndScroll(document.location.hash); + } + // If no hash, build the minitoc anyway for selected tab + else { + var divId = $('#content div[aria-expanded=true]').attr('id'); + generateMiniToc(divId); + } + + // Handle click on internal links + $('.ui-tabs-panel a[href^="#"]').click(function(e) { + var href = $(this).attr('href'); + hsExpandAnchor(href); + selectTabAndScroll(href); + e.preventDefault(); + }); + + // add sticky headers to tables + $('table').stickyTableHeaders(); +}); + +function copyToClipboard(text) +{ + if (window.clipboardData && window.clipboardData.setData) { // Internet Explorer + window.clipboardData.setData("Text", text); + } + else { // Fallback solution + window.prompt("Copy to clipboard: Ctrl+C, Enter", text); + } +} + +$(document).ready(function() { + // Assuming that the ZeroClipboard swf file is in the same folder than darksun, + // get the path to it (it will be relative to the current page location). + var bbScriptPath = $('script[src$="darksun.js"]').attr('src'); // the js file path + var bbPathToZeroClipboardSwf = bbScriptPath.replace('darksun.js', 'ZeroClipboard.swf'); + + // Add copy to clipboard snippets + $('.org-src-container').prepend('
      [copy]
      '); + + // Display/hide snippets on source block mouseenter/mouseleave + $(document).on('mouseenter', '.org-src-container', function () { + $(this).find('.snippet-copy-to-clipboard').show(); + + // Need to call zclip here, once the button is visible. + // Beacause when the button is not visible, zclip does nothing. + if ((window.location.protocol != 'file:') && ($(this).find('.zclip').length == 0)) { + $(this).find('.copy-to-clipboard-button').zclip({ + //path: 'http://www.steamdev.com/zclip/js/ZeroClipboard.swf', + //path: 'styles/darksun/js/ZeroClipboard.swf', + path: bbPathToZeroClipboardSwf, + copy: function() { + return $(this).parent().parent().find('.src').text(); + } + }); + } + }).on('mouseleave', '.org-src-container', function () { + $(this).find('.snippet-copy-to-clipboard').hide(); + }); + + // Handle copy to clipboard (here, for a local file only 'file://...' + if (window.location.protocol == 'file:') { // if local file use browser-specific code + $('.copy-to-clipboard-button').click(function() { + // Get the text to be copied + var text = $(this).parent().parent().find('.src').text(); + text = text.replace(/\n/g, "\r\n"); + // alert(text); + copyToClipboard(text); + }); + } +}); + +$(function() { + $('li > code :contains("[X]")') + .parent() + .addClass('checked') + .end() + .remove(); + $('li > code :contains("[-]")') + .parent() + .addClass('halfchecked') + .end() + .remove(); + $('li > code :contains("[ ]")') + .parent() + .addClass('unchecked') + .end() + .remove(); +}); + +$(function() { + $('i :contains("[#A]")') + .replaceWith('[#A]'); + $('i :contains("[#B]")') + .replaceWith('[#B]'); + $('i :contains("[#C]")') + .replaceWith('[#C]'); +}); + +function togglePanel(e) { + e.preventDefault(); + + $("#left-panel-contents").toggleClass('active').toggle(200); + $("#right-panel-contents").toggleClass('active').toggle(200); + + var slidePos = + $("#left-panel-button").css("left") == "-23px"? '182px': '-23px'; + + $("#left-panel-button"). + animate({"left": slidePos, "opacity": 0.9}, {duration: "200" }); + + // if ($("#left-panel-contents").hasClass('active')) { + // hsHideTodoKeyword('done'); + // } else { + // hsShowTodoKeyword('done'); + // } + + // return false; +} + +$(function() { + $('') + .appendTo('body'); + + $('
      ') + .appendTo('body'); + + $('#left-panel-button').click(togglePanel); +}); + +$(function() { + var ul = $('
        ').appendTo('#left-panel-contents'); + var countOfTodo = {}, listOfTodo = [], totalOfTodo = 0; + + // assign the counts (avoid double-counting elements from the ToC) + $('span.todo').not($('#table-of-contents span.todo')).each(function() { + var $thisTodo = $(this).text().trim(); + + if ($.inArray($thisTodo, listOfTodo) == -1) { + countOfTodo[$thisTodo] = 1; + listOfTodo.push($thisTodo); + } + else + countOfTodo[$thisTodo] += 1; + totalOfTodo += 1; + }); + + function scoreTodo(t) { + switch (t) { + case 'NEW': return 1; + case 'TODO': return 2; + case 'STRT': return 3; + case 'WAIT': return 4; + case 'DLGT': return 5; + case 'SDAY': return 6; + case 'DFRD': return 7; + case 'DONE': return 8; + case 'CANX': return 9; + default: return 0; + } + } + + function compareTodo(a, b) { + if (scoreTodo(a) < scoreTodo(b)) return -1; + if (scoreTodo(a) > scoreTodo(b)) return 1; + return 0; + } + + listOfTodo.sort(compareTodo); + + // display + for (i = 0; i < listOfTodo.length; i++) { + var $thisTodo = listOfTodo[i]; + $(ul).append('
      • '+ $thisTodo + '' + + ' (' + countOfTodo[$thisTodo] + ')
      • '); + } + + $('#listOfTodo') + .before('Next Actions (' + totalOfTodo + '):
        '); +}); + +$(function() { + var ul = $('
          ').appendTo('#left-panel-contents'); + var countOfDone = {}, listOfDone = [], totalOfDone = 0; + + // assign the counts (avoid double-counting elements from the ToC) + $('span.done').not($('#table-of-contents span.done')).each(function() { + var $thisDone = $(this).text().trim(); + + if ($.inArray($thisDone, listOfDone) == -1) { + countOfDone[$thisDone] = 1; + listOfDone.push($thisDone); + } + else + countOfDone[$thisDone] += 1; + totalOfDone += 1; + }); + + // display + for (i = 0; i < listOfDone.length; i++) { + var $thisDone = listOfDone[i]; + $(ul).append('
        • '+ $thisDone + '' + + ' (' + countOfDone[$thisDone] + ')
        • '); + } + + $('#listOfDone') + .before('Done Actions (' + totalOfDone + '):
          '); +}); + +$(function() { + var ul = $('
            ').appendTo('#right-panel-contents'); + var countOfTags = {}, listOfTags = [], totalOfTags = 0; + + // assign the counts (avoid double-counting elements from the ToC) + $('span.tag').not($('#table-of-contents span.tag')).each(function() { + var $thisTagGroup = $(this).text().trim().split(/\s/); + // \s matches spaces, tabs, new lines, etc. + + for (tag in $thisTagGroup) { + if ($.inArray($thisTagGroup[tag], listOfTags) == -1) { + countOfTags[$thisTagGroup[tag]] = 1; + listOfTags.push($thisTagGroup[tag]); + } + else + countOfTags[$thisTagGroup[tag]] += 1; + totalOfTags += 1; + } + }); + + listOfTags.sort(); + + // display + for (i = 0; i < listOfTags.length; i++) { + var $thisTag = listOfTags[i]; + // $(ul).append('
          • '+ + // $thisTag + ' (' + countOfTags[$thisTag] + ')
          • '); + $(ul).append('
          • ' + $thisTag + + '' + + ' (' + countOfTags[$thisTag] + ')
          • '); + } + + $('#listOfTags') + .before('Contexts (' + totalOfTags + '):
            '); +}); + +$(function() { + $('.done').parent(':header').parent().find(':header').addClass('DONEheader'); + $('.done').parent(':header').parent().css({color: '#999999'}); +}); + +$(function() { + $('span.todo').click(function(e) { + var orgKeyword = $(this).text().trim(); + $('.' + orgKeyword).toggleClass('selected'); + $('#content .' + orgKeyword).parent().parent() + .toggleClass('match' + orgKeyword); + $('#left-panel-wrapper .' + orgKeyword).parent() + .toggleClass('match' + orgKeyword); + e.preventDefault(); + }) +}); + +$(function() { + $('.tag span').click(function(e) { + var orgTag = $(this).text().trim(); + $('.' + orgTag).toggleClass('selected'); + $('#content .' + orgTag).parent().parent().parent() + .toggleClass('matchtag'); + $('#right-panel-wrapper .' + orgTag).parent().parent() + .toggleClass('matchtag'); + e.preventDefault(); + }) +}); + +function clickPreviousTab() { + var active = $('#content').tabs('option', 'active'); + // Avoid going back to last tab + if (active == 0) return; + + $('#content').tabs('option', 'active', active - 1); + + // Set the location href + var href = $('#content div[aria-expanded=true]').attr('id'); + document.location.hash = href; + $.scrollTo(0); +} + +function clickNextTab() { + var active = $('#content').tabs('option', 'active'); + $('#content').tabs('option', 'active', active + 1); + + // Set the location href + var href = $('#content div[aria-expanded=true]').attr('id'); + document.location.hash = href; + $.scrollTo(0); +} + +function orgDefkey(e) { + if (!e) + var e = window.event; + var keycode = (e.keyCode) ? e.keyCode : e.which; + var actualkey = String.fromCharCode(keycode); + switch (actualkey) { + case "?": // help (dashboard) + case "h": + togglePanel(e); + break; + case "n": // next + clickNextTab(); + break; + case "p": // previous + clickPreviousTab(); + break; + // case "b": // scroll down - should be mapped to Shift-SPC + // $(window).scrollTop($(window).scrollTop()-$(window).height()); + // break; + case "<": // scroll to top + $(window).scrollTop(0); + break; + case ">": // scroll to bottom + $(window).scrollTop($(document).height()); + break; + case "-": // collapse all + hsCollapseAll(); + break; + case "+": // expand all + hsExpandAll(); + break; + case "r": // go to next task + hsReviewTaskNext(); + break; + case "R": // go to previous task + hsReviewTaskPrev(); + break; + case "q": // quit reviewing + hsReviewTaskQuit(); + break; + case "g": // refresh the page (from the server, rather than the cache) + location.reload(true); + break; + } +} + +document.onkeypress = orgDefkey; diff --git a/examples/export/styles/darksun/js/hideshow.js b/examples/export/styles/darksun/js/hideshow.js new file mode 100644 index 0000000..e528759 --- /dev/null +++ b/examples/export/styles/darksun/js/hideshow.js @@ -0,0 +1,335 @@ +// hideshow.js --- HideShow JS file +// +// Copyright (C) 2014 All Right Reserved, Fabrice Niessen +// +// This file is free software: you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation, either version 3 of +// the License, or (at your option) any later version. +// +// This file is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Author: Fabrice Niessen <(concat "fniessen" at-sign "pirilampo.org")> +// URL: https://github.com/fniessen/hide-show/ +// Version: 20140912.1722 + +// var HS_COLLAPSIBLE_HEADERS = $('h3, h4, h5'); // collapsible headers + +if (typeof HS_STARTUP_FOLDED === 'undefined') { + var HS_STARTUP_FOLDED = false; // Show just the overview, or show all. +} + +if (typeof HS_SHOW_ALL_TEXT === 'undefined') { + var HS_SHOW_ALL_TEXT = 'Expand'; +} +if (typeof HS_HIDE_ALL_TEXT === 'undefined') { + var HS_HIDE_ALL_TEXT = 'Collapse'; +} + +if (typeof HS_ALWAYS_DISPLAY_ICON === 'undefined') { + var HS_ALWAYS_DISPLAY_ICON = false; // Display an icon for all states, or + // just when closed. +} + +if (typeof HS_ICON_CLOSED === 'undefined') { + var HS_ICON_CLOSED = '►'; // black right-pointing pointer +} +if (typeof HS_ICON_OPEN === 'undefined') { + var HS_ICON_OPEN = '▼'; // black down-pointing triangle +} +if (typeof HS_ICON_EMPTY === 'undefined') { + var HS_ICON_EMPTY = '■'; // black square +} + +if (typeof HS_SHOW_ALL_OPEN_DONE_TREES === 'undefined') { + var HS_SHOW_ALL_OPEN_DONE_TREES = false; // Expand all will open DONE trees. +} + +if (typeof HS_CLASS === 'undefined') { + var HS_CLASS = 'hsCollapsible'; +} + +// Expand a header +function hsExpand(header) { + hsExpand2(header, true); +} + +// Expand a header +function hsExpand2(header, expandDoneHeader) { + // Ignore non collapsible entries + if (!header.parent().hasClass(HS_CLASS)) return; + + // Do not expand DONE node if not required + if (hsIsDoneHeader(header) && !expandDoneHeader) return; + + header.children('span[class="ellipsis"]').remove(); + if (HS_ALWAYS_DISPLAY_ICON == true) { + header.append(' ' + HS_ICON_OPEN + ''); + } + header.parent().removeClass('hsCollapsed').addClass('hsExpanded'); + header.nextAll().show(); +} + +// Expand a header and all its parents +function hsExpandParents(header) { + hsExpand(header); + header.parents('.hsCollapsed').each(function() { + hsExpand($(this).children(':header')); + }); +} + +// Collapse a header and all its parents +function hsCollapseParents(header) { + hsCollapse(header); + header.parents('.hsExpanded').each(function() { + hsCollapse($(this).children(':header')); + }); +} + +// Collapse a header +function hsCollapse(header) { + // Ignore non collapsible entries + if (!header.parent().hasClass(HS_CLASS)) return; + + header.children('span[class="ellipsis"]').remove(); + header.append(' ' + HS_ICON_CLOSED + ''); + header.parent().removeClass('hsExpanded').addClass('hsCollapsed'); + // header.nextAll().hide('fast'); + header.nextAll().hide(); +} + +// Toggle a header +function hsToggleCollapsing(header) { + if (header.parent().hasClass('hsCollapsed')) + hsExpand(header); + else if (header.parent().hasClass('hsExpanded')) + hsCollapse(header); +} + +// Expand all headers +function hsExpandAll() { + $('#content .hsCollapsed').each(function() { + hsExpand2($(this).children(':header'), HS_SHOW_ALL_OPEN_DONE_TREES); + }); +} + +// Collapse all headers +function hsCollapseAll() { + $('#content .hsExpanded').each(function() { + hsCollapse($(this).children(':header')); + }); +} + +// Collapse all visible headers +function hsCollapseAllVisible() { + $('#content .hsExpanded:visible').each(function() { + hsCollapse($(this).children(':header')); + }); +} + +// Add click events to H3/H4/H5 headers which have contents. +function hsInit() { + for (var i = 3; i <= 5; i++) { + $('#content .outline-' + i).each(function() { + var header = $(this).children(':header'); + if (header.siblings().length > 0) { + $(this).addClass(HS_CLASS); + header.css({cursor: 'pointer'}); + header.click(function() { + hsToggleCollapsing($(this)); }); + + // Allow to override global Collapse/Expand default on an entry + // basis (see property `:HTML_CONTAINER_CLASS:') + if (header.parent().hasClass('hsCollapsed')) { + hsCollapse(header); + } else if (header.parent().hasClass('hsExpanded')) { + hsExpand(header); + } else { + hsSetDefaultVisibility(header); + } + } + else { + if (HS_ALWAYS_DISPLAY_ICON == true) { + header.append(' ' + HS_ICON_EMPTY + + ''); + } + $(this).addClass('hsEmpty'); + } + }); + } + + // Add div to hold minitoc content (so it can be cleared without deleting the buttons) + $('#minitoc').append($('
            ')); + + // Add buttons + $('#minitoc').append($('
            ')); + $('.buttons').append($('' + HS_SHOW_ALL_TEXT + '') + .addClass('hsButton') + .click(hsExpandAll)); + $('.buttons').append($('' + HS_HIDE_ALL_TEXT + '') + .addClass('hsButton') + .click(hsCollapseAll)); +} + +// Returns true if a header is a DONE header +function hsIsDoneHeader(header) { + return $('span.done', header).length; +} + +// Sets the default visibility state to a header +function hsSetDefaultVisibility(header) { + if (HS_STARTUP_FOLDED) { + hsCollapse(header); + } + else { + if (!hsIsDoneHeader(header) | HS_SHOW_ALL_OPEN_DONE_TREES) { + hsExpand(header); + } + else { + hsCollapse(header); + } + } +} + +// Expands an anchor, i.e. expand all parent headers +function hsExpandAnchor(id) { + // alert(id); + if (id) { + // alert($(id + '.hsNode').length); + $(id).parents('.hsCollapsed').each(function() { + hsExpand2($(this).children(':header'), true); + }); + } +} + +// Search for next task to review, starting from beginning of current tab. +// If BACKWARD is true, search in the reverse direction. +function hsReviewTaskNext(backward) { + // If no tasks to review at all, do nothing. + if ($('.outline-2 span.todo').length == 0) return; + + if ($('.hsReviewing').length == 0) { // reviewing is starting + $('body').addClass('hsReviewing'); + $('.hsReviewPanel').addClass('hsReviewing'); + $('body').prepend('
            '); + hsAddReviewingPanels(); + + hsCollapseAll(); + // Get first task to review on each tab and expand it + $('.outline-2').each(function(){ + var firstTodo = $(this).find('span.todo:first').parent().parent(); + firstTodo.addClass('hsReview'); + hsExpandParents($(firstTodo).children(':header')); + }); + } + else { + // Get all todos + var todosElements = $('.outline-2:visible span.todo').parent().parent(); + // alert(todosElements.length); + var todos = jQuery.makeArray(todosElements); + if (backward) { + todos = todos.reverse(); + } + + // Find current review item and review the next one + var foundReview = false; + var index; + for (index = 0; index < todos.length; ++index) { + var todo = todos[index]; + if (foundReview) { + $(todo).addClass('hsReview'); + hsExpandParents($(todo).children(':header')); + break; + } + if ($(todo).hasClass('hsReview')) { + foundReview = true; + if (index < todos.length - 1) { + $(todo).removeClass('hsReview'); + hsCollapseParents($(todo).children(':header')); + } + } + } + + // Update reviewing panel + if (index < todos.length) { + var reviewItem = index + 1; + if (backward) { + reviewItem = todos.length - index; + } + + $('.outline-2:visible .hsReviewingPanel .hsReviewItem').text(reviewItem); + } + } + + // Scroll to the current review item + $('html, body').animate({ + scrollTop: $(".hsReview:visible").offset().top + }, 200); +} + +// go to previous task to review +function hsReviewTaskPrev() { + hsReviewTaskNext(true); +} + +// stop reviewing tasks +function hsReviewTaskQuit() { + $('body').removeClass('hsReviewing'); + $('.hsReviewPanel').removeClass('hsReviewing'); + $('.hsReview').removeClass('hsReview'); + $('#hsOverlay').remove(); + $('.hsReviewingPanel').remove(); +} + +function hsHideTodoKeyword(kw) { + $('span.' + kw).addClass('hsHidden').parent().parent().hide(); +} + +function hsShowTodoKeyword(kw) { + $('span.' + kw).removeClass('hsHidden').parent().parent().show(); + // XXX Show if parent is not collapsed! +} + +function hsAddReviewPanels() { + $('.outline-2').each(function(e) { + var nbItems = $(this).find('span.todo').length; + if (nbItems > 0) { + $(this).prepend('
            ' + + 'Press r or click here
            ' + + 'to review ' + nbItems + ' tasks
            ' + + '(out of ' + nbReviewTotalTasks + ' tasks)
            '); + } + }); +} + +function hsAddReviewingPanels() { + $('.outline-2').each(function(e) { + var nbItems = $(this).find('span.todo').length; + if (nbItems > 0) { + $(this).prepend('
            Reviewing task 1 / ' + nbItems + '
            ' + + '(out of ' + nbReviewTotalTasks + ' tasks)
            ' + + 'Shortcuts: ' + + 'r (next) - ' + + 'R (previous)' + + '
            '); + } + else { + $(this).prepend('
            No task to review
            ' + + '(out of ' + nbReviewTotalTasks + ' tasks)
            ' + + 'Shortcuts: ' + + 'r (next) - ' + + 'R (previous)' + + '
            '); + } + }); +} + +var nbReviewTotalTasks; + +$(document).ready(function() { + nbReviewTotalTasks = $('.outline-2 span.todo').length; + hsAddReviewPanels(); +}); diff --git a/examples/export/styles/darksun/js/jquery-1.11.0.min.js b/examples/export/styles/darksun/js/jquery-1.11.0.min.js new file mode 100644 index 0000000..73f33fb --- /dev/null +++ b/examples/export/styles/darksun/js/jquery-1.11.0.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m="1.11.0",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
            ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f +}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="
            a",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/\s*$/g,sb={option:[1,""],legend:[1,"
            ","
            "],area:[1,"",""],param:[1,"",""],thead:[1,"","
            "],tr:[2,"","
            "],col:[2,"","
            "],td:[3,"","
            "],_default:l.htmlSerialize?[0,"",""]:[1,"X
            ","
            "]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?""!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n("

            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ðB^hs?eSG?_|9nX5btsyx8pgocGI2Gu!%-X+`=| zA{oPGHv|=!1WPsM?`RRwTX#30#ASc4+xHR={n81Sc+Mm=XkBPq-m&yYr*J@eiA6z4 z@cOS4v;H%9xQVlWXwJJl>FNRQ#S-%Q7VM1-LWipu!;Y`oa$wuM1cpTQZ=DPmKAoMP zD*r95{u`fW$Ez&8rV6H_1$revT9XUQa$Zkhd(f1>o7H|nX>|Vg{$Jgf3%U;{G?ZGh zCB!p)pVVeMfl0-i$32}v?Zvi>4(xF!q}4k*Ywnk;oSrVRfvGq_uGN6C$-JWFzkaJd z&-Y!ex;y6N@v~?CXtw;orsG*rx4!%4hWQ3JJj%+;r(M@L60}8d1siLWiKG7N!V^l$ z3Nz=ZH*s(AP<>1!5!?^*2sE6==ly$8z^ry0x6|D5E> z5+B{bThTf-zj8zT{}nnC+X{_}}jrR0Z)@pWEa#pc2T zj21iCK1ob!xxpa9JfEeAJ77jrtVWxVz@JSQ=3kJny*6Q8OGDN5=T$f2d0$@orqI19 zFTR8=qDEYxmeEV$;&GvtpTAD|*EQ^_IU~-!C7^pVQ|+wltqLpty((v9;A*pbz?`t5 zX>s_s;|1KWw*ONQ;Jx+y_e=HvpW-`C7*yuZ*Lomc|J7bW?Ppi%{F#LLgJ@fAZ z9Yo9cE%ts@+l!|31*|$BSo}Zy|8vd#f9(BVODz5$zwveL^hpYxU+?qx#@_$6M?#cP zm&iTf7N}Hf|n$6~C2T!rME zrsUnGtYe~T6{Z?GTQy?2nvRv4d%1e*9t{gO4VQFHMRiSM3(cr?T9I8^$yM6ACVD;r zdI7z9v5^KDU52(9h9yUhbxn*dJdJ~jOtYt&nVOqrud`59x9ID$bhNT^53|-au`Zi! zqi1DfXkycT!M=5;vx$kTi?wU@Y&Xv^kLY%fS$913OuWp@yqo5DPdMePqwbs2`_bORsb@v-F)WGA7N*n7lF5Tqo1hGRHq4uj5#LXjXn+ zZ+>@4{?g?9Rp;{$ye!DiD(LPn*!HY2$g(&$w76(}@s^2Yk$T@hMY!il-btKXqgFw1w-ZSM*Ll zQZ?i1if5S^plN+K^s>VZd}>D@yx|dHWr(vcW%zf-I{5$tCI*=wiIt;{}mJo&=8br(-OxD=Omso46`ij2!kqp#d~bmiX5>**oa@0_@P z=f;g~r8o9A-#FNL<9Pgy6Vq?p*?HsM;~V#0KFSGuR22W%&*@2<-P5?#=O>b0#Du>J z@pu!T_GYTf*Uf?7k464Gk^F0=J1E(sVvhd|q8u_B0`m_xvvF$0oY=7NaJzuA*Bpf4)J+kZ8!*~z$l-QC?4pI_ZQy*)oly892;zEcUF^VT#RSCc!lV`IWXR_Q}Ksv_o3 zUs;@|abUrVE1CgStKzOrw|ryf5FuT=;F@y+OLByLi*MqxZEx4+%Dz`kbo07;XV>ym zS9!MX`1nX|iH!c7<%vbD%A4%$|7}ra7S>(nB$wgTH)mzhDS`iq2BISKgD2Y*n5ix= zuKM)r%wlt14@KtWjEWtLe>vXU=EilB?HY%lL*g+hKMTk3umh~+;`#dmuZoq5gk?Nz zl{Rz_Ea5AA@i6vBgF>6IYlkAMU1FnAv%{Q5r>h#y1z}v=5F1N$KF#&T!xs6T358c@{(7?N{JOACtE*h)E{8hgw96)(knOZ!)aG8fO0ZKlWG7d4 zsQ0VG9Lg;mPjc6UJ6b;zTD57G-ii;)TK&b$dK8a|1T5f~*2T28L2gyZ$qwDnfBVeE z`k87s@Y?bi+xYYIthmI@&oA7P65$nel!4FhN<*_`QN;&`NWBov)ahT_PA`yTopo@n zU6YsOy18G{*6`1cxMnaj%v52PE3b`5=h8;~%X2=3)w5Y;EQ_r9v&qi%#>&()E$4bR zowcZ6`1xe;m4KF(@YOQ!Z=_7tW!tsHFI8)mw}X*$VoS)@8zD&{Y!a(nJ&Kr_T^Ib1 zc2P>vD7eDZy>)@){i@Hs>+I6QL!Dcarrc&!GSS(1g1uZLP(sPs<-+zm-LDTn3@z67 zGgr*n&08MYJN@mhP{mu@jtTzCJG!39;Ea2yoKe)&-zuS@%dTdIe+@bm9?ZGIpn*A- zXWH5Dt)@k}Spw|KWHqJ)JPXsCzo&erxsSjyrt9hZ|DL_j%=$3DSo5vp&s*yozsNQO z-JNzRlvjPi;)nhG|9?(V@}3@LFya5n_oW;@585v+>)&cvkoT)$0aubL+o~O}gPJcL zfBvLxDtDSfb3$Y^yMiKXHrEuy7&wia?fE3F<7M5(oY-Q!@DR!nwokPGBvYkfF(u1p8pl!!{eHaw>mh*L``oak5Zp^UJGlmRt*b z=bSmPSKa4n&94`{oO~L`EPPvi74Dq+rII4X$#IG~cTaEFq_q83_aPg@g2}+(NxGcU~9;bQBsc66mxD7JQT@n*7#_an2VN zjn3Ao)*_FlE|*%!kyCI;B#UF}mR*T2+^!!wn%dX;YeC8j6;HF8n3ZOJKN7?8+83|9 z;~{9gtD!e(35U4lG$ccJOh=sDLnSM~nDwez{l@uU$Hm09lw?mz4 z%OzWR;ef@u~VjF{Ify`-{rB9Ae_!>N~nkQU7J>mES#!vG?PCmC=UUZ?} zuPZBj=e^%CZ2px=FBaQXK3LhpxoefkGJd-qETKm2QvHU%fXjJQ+a$$w(fG>wpl zLZ_B8#JLqrH`vm}lPTfjZB{VjNRPPPkp(AAI~-?5?3Ar}GI`$DEzjeFZTUY;$(WjH zVwm_T;t~6UjV`Pf`E?B`cSDm9=+IeLF8q=Z6HN$gvAcr5(O%X$hSTQClc^ zu7b_v)m8TDm%&qgRJ zABwbn7pG^VbM>0L=|2Urv@m0LrqvgX*RJH3(A?;5&lM!nnQ~NnS!+b_{{>#A0gFXd zwpMC;bd{AP@G49XPGt_BcqByUqQLxDi`hdMci0{AnmRpORYt0t**Z<&Gic5v*l~w8 zM^J94&7W7xL&bbn8XZizx;1=1*EO$l-{e&Z;;(~O9z3#q(x>eA*{)m;Ne32KZb(i1 znvfcL!~7tpVQ1i*n~!WNLwg>+En}$F4x4}K;Z~vCCBdm5k9hq#FWOLCn{$}AAi*+h zPi!+6eS-|2jgR4&3e(I@syU&6C7NI?c+*@wTO)@r14E4#dIyNz= zxk31jO|nH6+fKK11>Tf07fSiR?egpclxJ6!*z zA|&{9ciL({Tw#51`Jtk$3I(gD%efk~?5E}A@78*4Zu95te9;#7M6LhZb6>K{KX$JV zQ!Hg>td~n@*nYi%)5KB9z{}E9)HzgCIz^PX+;R2Oh9Bvo7qVZqZl=$Ey451;Sm$!*-HByst6MgNT%_LZ8aYDe@Ty!Us!bL%D4t51A3(?^A;x_^H zo6<$w!dq@#D?WRz`RF44&&&BeD;oS~H2-4AmbuZI`k0}}fw^3P-B3Vp|CL~|AJq>Q zu`o|$TxcS?x2=>%fc^V&e)kWJfvn|cuM}Pp@x8pIU2ePREtN{M7rwm0erc?A2cA@# zSFi>DH>~@h&N@jWCc?1cjl1Xt@y^LNs=`*Zl%8m@UC=pcg{Xx&_rnJqTiZKJ!{t3H zL^)14#k^?U#Gzk4fpuR~K}cYuG`%*%E^fT_tp5u_TCdeD*H2n+%m$f%tene zRB#tg%rqDM{r?-I;YxmE&&s(w#Jb%@+t?>>cAw0`DBsIaf3ms%mxsg^waHA9Q~Max zv>G^~Hm1gJj}9>x-LKA;{Dbv`xz9=SX&$OmGbW~Gvx&QF0?Fw`meWfj zr3!b0b}H#>Kc}Z1Euz zbG}^7S^Y6*y`XfGA=B)Y{P)D>d}x{#(#U*TfIHN2&Vr;lVT`jJEyYeqa!WmA2x07x zb}URVoLhTvZrH;)xile@bl{~hudJ`8e4o#f<>%$V8X{suhDlWiZ{&RcczGVzvitu#x_>cD5WLbjcUfuJ#nMnlUB_qI2b6S< zsHdfcPYhPny^^H+BFQT%X_evEzmBpY|@%%CF;@Ydrx(OW`L;0EG5N?a%Br; z)f20~tSrC(#X!*5uwzEY@0~oG8TuD=b|1aYEW|MDq4;uv1$(bm?ersm@L#q`b8)w=EtbK1K zdgB+v?49f{rCgtQb>3gevzcKz&w^%-Xi?b&?u`t~Dy>9Wx)(f_at&(G3OK+O@^IPP zDADa%8=Z1DJ0&B3oHZMHWR-7A`wYq>0=(E7T$=pJU@eUE#7DcGE5>;1K%R&Be@ zFHW(DUvpX#7uPc|ZBtkhY{Rskhx&?ONMO? z%cCA{D_G4C!c|eUn!lub+ox4LGaEL{ow;PELQ>cE9lfi0>J>JGHZB+3CHi3Hy2wW6 zQxDiQH}FjGnlo?q92UbG`44O%6L*9b&Ww{@c+PV-*TY>Kw6g>>8Z})SnH)oc3mf-k zIEFCxL@0WzO$ioy;Mn|V&)rS4TwNFbT3~cQVnv1K*5KW%Kd$6=bul>bKWowN$xZ$t zlR`p@ehD;hEL>uHU}t-jLpC?-tlt}LH!zrGaV~$od?%NfyTSh8kK0e~oHLhO>_*mp z^R6A+7OeYudYKLToJhl+i6RForDk!jSu*XxK8ET!LOf!;tN6=S7bSjV%h6i0YW2ZW zoQV;NJ6?4i3`^WSLsLMf=g=~?wj__Xv=vMD9GQ@Pqb>i&mdL_j|7l*2H+ebz@m$E_ z^CZmq`cuZd3bo?oRb6HxvKz$2ju)PP(k?w+S#6hZ*hSw}25TCY?+ab1`e!AN+krW= zJJ*Ig?(Xgu>;J%=t+3R&YbL|CgQBlDB{lBWI-_Dx&cbQ4TmR1Tsk3+F=4`82!#{tu z=)(WpVp=k6!3t}2_UyW{Q{(TC6B~aYZ;07l_Gf>|nUkrmc2m#HnIG1@JwkMs#hyJk zR+@M331>WV#(H5ohwP=>sYXXn?F*f5rogq}Cr9n;h1#B>@5S=>c;(-87rkUrmnIs< zncSy~ITYFA$R~-sfT%A_l^S`zJt&ZOFHT*5ra~G`MAf7F{Xtt=j&i>iahr%DS zbw=?9Dr~LR*>w8D`pAd5U)C)DwufQ4_r+fumhr9KJKJpnTjzwm;+DHRMEN9r1T-i9 zdT?qROHA6+*Z(WUb@}2nb8PoSwt3Pg?_^vd^ zlXp^#;-v4PlhiAFqZyYo#VkIxf%BKtvXGBU>J6~65Koqf4`H~rfqn%L{hnky=ABf3`LWa!3g z)tlB&*V)DMV8z}&*Nh9U|8kf+*;jM|*Rn-DnIV}|BO9mgJ|S@R+SGW-X(10U&B;nR z_2`yVa%zN|#JX0!XmM?q(v*PRw@Z|#rFPE9knGObIIT+XV!Mye|C)uTY$bMWzcbH_ zwYp$&*u*;%T<)H$y<6~+k$cjm8@-vq|JU%hbe!`{y?ZzI-u|D-H!|Ra|J09pXJ+(7f9?4;P5xbjmXNck_Kbar5A&VW3+8bq zU%ke0)$E~Y++#+`!tCX%b(|K3`zR}C9labS%5m97;}&he*kEdMR51weVU-MtiZ_}=lEO#_(-?N;1&$Jen-MU$3 zC0Bmn*WR-0dmm}9Y4>1Ow-eQT_u#NmMXUR@P{qoYb5kz-XRrM1v20y?<@`NUb@K{Z z%tf7VzL?1_Kf9sw_p@hn?!BD%?HnzPfJD>~vXE#Dd*%@ryAC_4H~2;;VcE*&TC zoO#_Pc4ANcr|qKCPF#Kaz3yQ~o!!m8UjcpI5u!X2J{7r-Px0l=jC>U)=u+y}^q~8> zQeTsng_ck=lL-U6T4s@!XLD?hXz+3dA->iVpPMr>`dunS-G5AuHq7o#VBctvz3u>m zX~&W`5uz(CN*3IE|L@=XEW7s7iuPi@j@lDUm!=%OzUAn{x4lQBN-S4)WMrJvwG{1p z(VHQ`H~Ghg(2cKWP49fTkcUPyqNquLsWD7r@#;OVIMz*|5yBcI_~pS zwVoqCo)q7kcaUfPXS4b1S>_#ofDt8|T!{{>@+W`-;s;KEqAU4oesR`+Z~n zU)98g&HoJ-W(uB`KlrzP<-A`T@@)3^9On5F6}XeIIl$*8Tlf|6fk= zU){sM8H@tuQ#2GJEO|0 zb6p_QC)Kn`gqx>1Vo}J=397DM=cR(Yt|c>yv}bVjE!dJXQ{REN(M)6&LrdTaEA?d= zE4a9fQm5J3<-A((a9-OqF)`a&Qyxcd$-KHQ_4c*5(K`x_UoEt7VQf|{dv|AJar1*N z>xmLCXFlBEmf*%e*W?ZN#C3zu7^pry^7is ze?-W~?XAhT5y`ml`G3OX4f}sIc0`q?)K1p6FVVgJqwtB;N~eJl&Op&VKS3W zt?mFV3x6UMQsBrYT_Rv_^(x(_Vomlg^nG;HYTynhlDLN=+LV@|c$tZf!5(DLkU`u_?$^ zZ2A>w>(e7ECxPq3IGI)qZt($HR=*+b1Zp9x8g!#D8!4iO9c4 zUf;X$CG}EbePwAzc$fO-87`H&?ynQJG&-Hm- zo5RCo>nT1HohQECFnP|Iu6qVvd)k&M`0q7{xa>a3V9trCFQ2X%|5e&tm-4pjF_7km-jaZmALoccOb1~-@L!^YF9 zje;h%S1eSV{DIrcuaGN1#J%xX!UETCEb2`HFBCWa@OLqJ@qa>uMT=d~#JNV(o=qv5 zo1GO}?ZM9Z!%5K0ZdC_Y7ds0B^zPDxRg{psQ1Ry478N{Z@r zH&5@hpvkkJq^R5e^bCNkXLmA)^m5P3>06zWsvY|iWj*_|py|7xr0Ulq*0c9k`lP4@ z$K7sVH=Xhmyq^6~i=#``l77zr=N2~3XkNe~z36Or&S4#a%p>e8E;2V=I3V$5fjfun zr^fDrkBYq+kEh2N`hpg;vwY!R>!ZLP^wOCxRiWvbn)=*Rv3kW5turkABLvtan0ajq z+@0+h_^Vzim$mIW!EQ9Mb5+Ws4E-(7?LZ6Kg}mooHCW&(=Po=WQeDlsa;C4In_!{b zkvaAp&iYc5Ix~G(=1K2-DIycpTj-Ut;@6Ef*J)Wii7yY&#F!lr2?Hux~r)cjBD$|G9euP6Qbj1=mV2=e=ck?Go~E!a1)eYado{ zMCAXv*|s2fwNELt%p@+s9l3{jrMF6D$~HySE-+S%chU`Kx4zZRaD6TB#$2!7>X>+= z1A63m-SlSCmJ7$XfkjR&FFA+{hG*_9ALIbMv<3!(}DPo9Zd?KN;-Nt z)vp?cO;y}z(NvpxM?f-rs_f6Z>s>54zXz`ytBJD&p5j#&0y5YuXT`)Mb*HZMOl_usDO`JV9@=@Gug&(yXJD2)ql`OYT z^|wt(lreH-(>l<2*XIG#>*(zEltpvSUu(Cz`O*{wd?;oZ%}^Bf5CL~uGqqu z-rW1gwC+f(x_W%Vd8R~d^*d{M>^Zip=Z3bk$E*|B_^DPk>D`)D(NDGI)w*V{6x+NB zv7r5V%yaAKl~@_a$gS`|V9@--Vpk4c=UJJ^H8Vf5Ex@ODj&?*epEp zr0oY0{grAipAs6k*iU$47Tdt*lekOt!$L*ok`wc!o|n&0WO>bNDdooXUSM5y>_i+xcmS zqbK^<&kt zaHc!Hj%+>9f@edj$P$gCzx^7!0zD)qE}s&w^>m?su$jaB$d*|DQ!D=dmUWW)ZT=+b z=}rHQ`TjopF7J=(?A`Z+`-lS1VFw<~Al`Njz6Sz)rw{O)eb958f%l?9FSpF%D?7Fy z|2=;yvq)`5U+0C!z!^-g60FJrEp3V{LOi=)Ty7Wdv2#^mezkbryB~cYD)`qL3w+C1 zd2!+7pA-5Wsyh_c@C#&4caLCOt;xTuij6~gPy3DLH5CnCX0ZOs=+N48Xzoug)j#_a zgOs^4JGfVh@;(&cXA~4v6co#^4Kh@WLRfyudkx! z-Pmzpr%>kv=`D>M37i^T0TLE2!l8+x;Sc50uC&|F+39$M!`{KJR)IM!QsLR`BPRsi zCDt4fm1y+|VVdsHDE^@N_2!Pui@U6LiV3aU8>k}{k}~oq`Qwa(FKwr(a7;VM!M=+{)}l2qpox3JO!W$;tK7#sIu3e1X<@%$U0Wf0PUDE* zoQ|A_l8Y{CF8n#S^2qVpDYgx_ofr#UdpEeoTygEF*t@*NgK?rq>aSUQA8y_*xHx5s zsEyFcjt1$S2f24`l*p}OPb$*zW${<^tAbZJh?!Cyl7YpZZy~45M=h3+VY`eU8{8dh@vGLFfVbgwd zsM6=GYLCZ;KT98Z>TmR!_cU{!>8?qpSK40+PWn>F)A2&SBSPu_i5iD(fRNI8EKh|^AO{6ZFcx=4k|7Z81zr|;-KT$PZwNTSZ z&icec*;9Rc3zQUs9NHav4{9hSnJBADoz(A|-?1S;Ym*XBD~BnQix_sC3*uT=LSkG6%|_>D04PY_HLlu+d%oRi>3btD#`{a=>{p=2C4W4sm2DWTcvW7;eThZVDG5Q z&sJ^hd0-)Z*O)aTxToN<+ofRdN0+S+1#f-fzm$2mPVACx(ZV^umgQD0;89 z(b?WlUa8xE+;fO!Z=~~z@L-L|=7VjUI6@b!o-ep$Qq%;w%U5<=g>`#`brgj42!!-B zT${WoY|DhOrHezSM6G%j!EftZrIUhtEhJ=!aQsKo{kH@7ER|k({r|ivbovcbyLY>crvSs$qS!@7z=4FN?HxFOB@VcKw>Q93QeabUwKK%64^o z?)`|+JDm>k$4xEz_C|dD%22%cel~Y3!?tj%qR93Kx3?bXTj?UiW*5UUFVgI<{#UQ7 zJnuHM6dT;ieIRF{&y=?`>Byv18_^DlV;u(ath&bxTHGQ9w{k^qUHkXey0;s6gs=H@ z%*}M3B>uRoOXI%4?1aM|9TBx*-(8Ku3k)T^*RpnOQWT4r#GNRkY}E1VVOQymzi01v zedyHq9nU!}iE*7$9d|Oj^&QRbj{mo7S6rI$i3A+r=2wEw$U_(Z6Lzo4`4))SfS=L?t!dc5Za*bvf;{b+JD8X2ZpapY}-3 z3Nn7xBH8yMG5N}h1rG6_O7CmrafQfnxifD`E4}Z`Y@#qh(B^bZhw%fg#gBg9HH-Wv zZ7rJ6^dSDH?)Fa8i&MK9|IIk! zT1U^SElZSAZPq0T@k#HS>FuU=u{|O2iR4VhL~r{k_K%HBLz2TgMSV^%hJ`nq9=#=# zcZDN}Z(HK+%{!)^$trGsxnuI#)O+(MMW=Lc`ybRetM}Bl6+&i7i-nh`Ftp#(5ZJf2 zCnBTbYKHaJr#Bp5b~oHLC{r(+!PsBc(cY)kduzq+p3KX(4_0L;rZ!7wx=rdA+b(UK z$$EMAygZJw9eoS#rB0l7c-Fj(+{GNz*zVdjzx?TvHTPQk?i%HVwet5|&;5-|=~Ll& z%qgf6DJ00b__w0aqbuziS$;dd9oTVAwXB%Wy?1+M_LcI@+czturfr<{BjP&8x@hHf z*Q=*mSgpOX+VRc)W!EQ9?NEMpdrQ$N%iK4M-aXH})^WV7BmTlOiS9@3!gty`-prf% zrv1R9tc+)!3UAHQu3NgjO;dY2W9ggxEgDC*am-=0oLSp(Zd%%Z?Z-+N+ZNu*4baVc z!YZ2G5paRKwZnsf*K^$jzFG?ttBc#(?is(8%GsN@Dp>XHvz>32b?6wdZG81Kmh1h; zG}X`R5@tSr_wL%x_wzbRzeXo?y$@TIKb!lK_qqJP_wxU}%m4o`pMk%CQNDmlzku1k zfW^OnHU5KxR&Z~@hjonwTPJ+@wyuCZahVa{vhR7^;cG9SK4)a!dRcO{q0hF{U_WSBaP#%$;r-9m)|SsuBA&J&yH7yl6)Is*uh_D_#b$&d=fy=C=6X6`{NF z*UPnvMUTB=^y&nX+BnSTf2w&D_PjvS-_Ll4#C6+pW3y}WSr0T%2^oq$X6*P;*kO>~ z_bR&ML~fm}nM!B#d^hc_Nvqw`SG8>@nQ-XKyt9$+{yV4hI^LCw+{hG>^Y8k%(wleI z=}cpNT+dqSD_**5Q%h=I3#&#X_qE6E9+4sGr88R71d2G4mfa0YFHHHavYL0zkFEEl z`owsvJJU}->|!uH-lS7DNyn(X!}$CclkYh>%5QGDnzjFEw8&_e*I-o0=-|1|e$VOp z!9#21E51*cU9&Rp)g2?tYel+mZp2tbtiQEs#TDMtENc9aSr_)?`COP zNZUvL|JGU?|7~s(kJuVH?yY{o*P1?9sJ}M;!TQU<`TiX7+ul20SyGP_YzxocSGj?C@Yi z6g>WPY^W-*tE)};a^O?$-AR88R#=fwxbBOOBOL2EKTDjn;QGB0{#vGLY2 zd8XBjT^w0$OsqUCO^=GRCb9E$`J4>=a_O*Ft!}*Aov=?2OxRXkSR!)EyOE>OCAh9* zhok)N<_xw~O_Nt9?v@K#tJPELlF&aT>FBNt<;MhfOZsyy;g;rnvBkU95;Vw3!}3W5Azcdk!p(K4J89N+a)`LUx8*ONug zn?=J@oK3i9JKmRc9o2S^igZ5tCp(Un7z0tTsD$){SRQ`G+jk z=a$~8RG(M*YNz`AT0iylxedQ8H5Rr?RcS2h)Y|pJt?3-+%)E(SR+>wvMpbDpo0+vs zbNSq=Uz#fxc3EkyTso^tYt_nCyR=rX-Star&Bjw!+H1Gos?uJ!^VKfx^?QH)(%x{8 z%UWmSQK@R3O((T>>uf%2^;>7lMK5dJtrI&Nm=^zvnXSA1Zq;wy9S_5{^UiuyH05&8 zrf)m0Eq^g-SKfrHr>yn&e!VrDQUAD%^Jyh^)=BHtnHmptn|SFQa4};_T(o}QSq;XC z{yazBefga(78lN9diwoB_(!qV@7BnxJo~szp<8Q{gV(IxMyGXm$NX2XobqV4uf|Uy z;|u$^g&!Y0a6G1{;LxvxNxaIgrwy5pgn6a$NZIUYo~*T(=Luh(Q0bqdlJNU0O|QjP z|24fKxi{|+_1ZsX6z~i*<4SS*r~*>T<9?EMue(s@TwE{9lRG#D^zAvo2NSUSHz>A9`=TQmmJ!|XUV^s zp3W+_SFSpIdt~QT_08etpNWSI z&ACKl(gSN=`ih{u&`d$X|3q4YGTC-2Eh#pw*jpIqSRyT$Gi4 zdOSkR^}lA4V{iDJ?duvnI9v`&bF@dS6cBp3QE}tyNhvuiU29WxrY-N8Zm=|H(OJh9 zS>ukhXDd!Bho0Lo``({t>m&r&#bg~P{(7+R)(tm<#v{Iygd%RJ8e2}>TUex+Vc_*h z&tuoOg+{78lb9TqGO%2;Xw%rIGch>9^H`Ler=r!LbO+X=3%4DgnyxHd%G7mpiELw! zqrl0tOVm6robe5oe|CjCB+VdbX~h=>0oE6eLW=}u9=oE@zDLvVD67y!lf22vGb7K+ zX--If|9~^erd}c*|`WHs&n>UIU zu`{mBd-B7*R^XVy(*K2L9A-&|P4UY#nz}I~XU-DKhZaZHHSX+*&Sef~zEl*%B6}|4 zYu5!PIhVCssoIg!r*7;nU@bX!G04w&b!6Vt_EzgN*Z2K0onXq~li(5Ra9i)>hGYw! zO!kvUj{I_p(2q0hSDzKo*KuT~^4_AgDLoxi=A86p{o*m7{ZU`vu^Xqd1YEbDQW0{Q zChZW%rBb$Acg>Oo++NDQ(><@Hc1&4!^6o1$K6|;UJK~pj-~761``%QmU}Nndo9~yl z@B6k_zwYzydpZ(_b=CLs)&H%Y$S^rzKbxIFldzA*v9sU3d5)cE7S(yk8NB0=*gk_c z<24U?i+3EB`)APMtn)~4@{YZN2g3e$2CsP}nqJ0Jz9U%R+5uOw%NConI$AP}lbU6m zQ;xHLEbP@~YHoevsPOROahVgza$i=YE4cd^xhzO%GfiPUDp+XPlge{Ww|M926-ft# zY?z*O^hC<5O=z0lew0CY3xkr{gk~8QrFJ6$MRn`OPM?e<;Tbn>s!p!(5ICd2rZ(ds zpYXw=3BqeL8ao`%*wlH<6hF%#&~cE{RlqqxzG%{v6D%Ukl1Bwng1E#I5(E~!`?8$# zgn&!GBkvQ(hVG?%*cx{v@MIS-E&8gMYFwk3wqalM8hNHB!x@ejtSdZLFJ05tcw)f~ zBRP(R-MMYzua$2dUG{B5w{Baq{;u0KSwkwv1YL^su$LMHVPb^wmya zHCLRpqElI*`?IA|T1HV1D^qsdbp|$<0)~xq9Wt_v8&B~q|8`=3z^8qW4se6sG z{o6Q%uQa@C-SW%Gux^G!l1)kDj*4$v<2_!5>wmp_U-KUG#obIH1p*Ja;}!m2Yv=!C zH{r4R|2Kc+PV^NDr8P4A{2|$~*>{- zp52{Bp&yqWJQP^x1uF>zERl6#OHugx@y3kCn+^vKD0$rHn3ljM;&jo#NwH#qorvS@ zrIIT+4z3fOEi5AE5+JjR^T1bxMLK#G#Y-px;$9P$j@?jvndOs*@4%*EpKF9PCtx$$=M@Wp(tUrfcaSB z42K1F0{1^Gb@}M3@Wyn$v&RC54-eVx<~vMSz{$5LY9$32Yh&osFxv2*>v_4$LIcrK_ z^u?_)Vpk6EMldYAo5Z`Nf&IlI$q$S4+2+aYShUu4k&N2nl0CDper^4hDSJKj?lnV) zJu4e`e|0r&Qn)oYLGcx{;w{fOL{P}L_}+Psce;e zBCfE+C@rP5XRgzQg$^!FyJT5B7R{Ep( zmbNr3Pc^)3X?UG#MBCDcKGn!+OC#q!4f`Y;yiPUxmiW#i;tQY1xz0(9zV`GA=Mk1g zPdD()bP}0qXESrs)#R!>%2Re;bMoOyxzJ!3(^Hty<6_XjC2(8n!2;(A2b|qnV*FTQ zo!V2=X2sU2xhniua=F5=mGQpO+8eXB-gMq0`R#1v+|(r1b4OIm=J;hKU2Bj)Ngr-)}#HH@MG(W!B2E-7j=OVl#V(lZXpE#aNx5b+>$+KnZlx0Y6>Ilp)y zuq^7>)F^(Tg?0_Ma-#%IfAn5?;jHH4?98y-X~{wdmje!OqSk9VJh&<^WaV;NQ+j*q z?2Vi*-!miakKLNm>$c5T?X9oksh4+Zy`t-^)Y}@R_uV}x>#^M7!jjf~3l1vIIi%Sl z$aQ4r&bj+#k8s^_RGD!5Rp+xqoJTkw%;)`bkS##^ht83mrVK2r4k%4=*#A=6c}8-Y z>7B!_caF%){hB(TKWmPi$V!(B|0g$2>Hm3w`Ip4uK$ouSU-N}$DNVSPwE6C%2QSpu zd(MTWR56gTP!x|YT&QAD=)+} z@6cVpUE&WoS4HSZB;OT5()VObZEr6xR3mT1U1&TETH(LGPr-t*`zcW}B4t{jKtkT=j`biyUU$chFe* z!^2IzcG66rm3bjA9ZVK-tZ+Cj$oTha{FW^BcPr$sO9qU;RcVk7nk#7TAxYxf8}`e?a9=>HsLq_ zbsoJs?D0rZ=}h21uPnb$Dx#}r%$(xwW+K6pZ#aEL&bAc{N;^Wuxb!5aZ7X)`@pdwk__7eso|=#ztr`Btnrj?9o(Rgb+(}}8V6;hdevyps!BcLh zW=iHNxxYKPY}xFCGv{24e0A)|t6#6@^1iuba`y6r$qqG>k|)hv6ZqD-=TqqvBQ5>U zn&L$+66?;_EoJaAHVxlw8gFctzS%6_*t~qRdA+ek`(}%NW6SBAE$16sE#GXl-q?Ek zX6yaNHpe&Hod0iZdwsL*ePg@lo9*5k+kf9||KHeweTxIXiKF-yNBI&Pe};ok7|ewm zgl{l9D{pb}H*pQ$;u>$_mcGR;zr;>^i;2q?GwTDlOc>p#Z}FUO;*LoB0TN=sB?8V5+*o7N_;s3~Rmw zs+XGSn40r9@apjB#vJ1GF=o7Q&@koD{*-1_4hF^mM*Ry;G9M24d^U;RzBPKkY0PHR zuWOtf_#61wiiNNX>av9D&S_w7VbXnZI88TjaYpXCsR+|R59@1TN zh=HRqcztP1`nI%uv-I-+W)9~|9lE!i7if^QF?F7OK)`1+^9obn(fc z>YPzkX-M*B_ALKu7{lz$&%iBmK>bHg?B;9P)n-NN+l%zS7x6blSd^JtmwP#UH}T%i z6tJBk!n~~gvp4sF0}fvqCZs7|@i8lD%<3;OZT~LYW3E4CyIHk~=k;%fe-0-94=_Ev zok7DS&DgyD`}X?(<=(;l`!1B4bN?_D_+cV#(Zt=*G~Jl>LsS0q?@ph;Wu-Dp&-q># zY;ic^N42zRe*f3@``ZK8f2(8O(K+9uYxxcba|Zq`KX@vPyLVTZ9=G7%V_|xEM{j>| z`TmmN?5zdGI~aDDnSTGl`R7M#`hVlP)8@79KPCwCc)tE#xO&GFf6J-iJ8j|}#28E+ zy0?7cVGy2SHpSawf^_BN^;?~oe=-Cd)cx|+V;=dLeU!5ra-Be*4gT}Wk)3Vz0m8JDR z4evM|cB!1-zH3GQuFmE%2j>I(-#A4%f925OF}66Q&hRr(UvTwqt2K*v^7~quMw^CZ zn}(m>X)4T+Y3Lj^-D0J@^(OV*o9>seY;b6j{<_J1_ZENat==YI?=&r!cQ(i=-&($V zd%g9J&Bg32qWc4?cFeclwS4!k_13$$@7|qk%y8uY?mg$N_g>$<_rCSM=ezg4x8DDK z_x}IZ2iW%<;I}y_zUQF4%^~$YhxBa@o9{VnZ*##MUqysyOV4uQ_JDhk@mwl?C(J=erpc z7%k@<*elMUvx8|be}nLr#=XLOFPhgd++fgK<7{?k+ez;2svEE zEX3(N^B#s54w@W$_X;0ScyjRKeg?rMe{YG`T(7Ua(f^kv#aTF^R%#9N{m-=*@@tQ? zGl*9lzQJBI%l)v`6y{sZ43|$^GjcH9-){53-|p#eYgU)TXYKb{#r&_`({G(iSK9s)_x|h5|8MX+NPXFNAh`biZ`)Vlc1O7F9t!_qaXGB? z;Q()s?VIDf8FU;tmoz>p-v4`l{T|`H78@8JA3pRad=K*hCzS~1zsxKQjm(@}4o>e_ z99y{=1q57l7@a$XHML51yp!tHdVS{UiXVbc+?i*Ewa$4Vu*h?&wkB6Y;3?*5UV@Qa z7Xq~wo@9)$*vRuzXqnF}CeM`YN5u;o7(K34S}QVShO7+MWP9)^SHoNAWnUA|hNb_d z*;gf>oMu`*ZPnqzX$(FcZReCbON$@!$vj}bZdJIosArA#g@u7#(aV=;-Ml8XG=J-{ zhSgt1Ja?L2JZ3A_vEW8bI5YQwS-)>ax}2HC$+ltQ^;=6j*v>j?E<5+hh5hJ}zl;r$ zGPAp9KUHEWFn=G{&&#`Vatr639ic_9g;s3VyW!5YQ#a`39ADE0o*9eQ9+unq`T5R; zj2r=tF?SZtVU7tu)-2kPdF5v3ve`}ZCNoF0-xf=@7F;nSP3Q%azKA936g#Cu2c}qC zT|C_Fr}pr`vY<@?M?`FknjRbo{v>gt!O>5$@Cc)&%*Vq^!X7X?vYy`k@=&naNlk}^ z99jo9tYqO>^j~upn@6&2JYS^ytaWOW^5OVWCY?+=Xm zZNHv!UbOXkl5_*tsRb?lUhiK_KB4gOnx^`~i`Qy=HxrNtk&lpecz)ME>a z?34>m%n4c&j42VzXLmU4P+h-YB-VXy@-Aif7Ly%J6Gbc@KTeXp&%(8!tH_9V_1cWA z#H6|D3pTX%nl0sI?#gKD%xDmDYiK?9$*bd_KzfElW2<)Q)2RytLUIw<}$>_nIg&@yyJg6WzthcDyj>aBpv*qiE;?S!<;Z2E8K_ zQ@Zp^D!E!*4$W9}Exn$%?Ej4<#u;T{*P}H1TTU%oz%27)%G%b*bao|2**LL6o&^VAa$vbgrSMW#;sxVCxEin2E!y%etQT)KPHS}s#{ z2EB7L?E7rlEcqFg)}=n`TB@V*ppm;RBB|?P@{DUqa&6nhGFR&Qw-wgSO!8R6!ZGJT z#;VkeMxhiB_bwrkbEVhg+_z3vI3g={Vr^8Y-{?hNF$}+XW?8eR3Ip@v45s#54h@c54ytL@ z2x>ffc4%>Ir#jEZhYm~)taJVxYxlo+P{ZcZVd1)#kT0K3-n{W$*{v`kaNaMGJD1Y- zeR}Gmr@+#qV8FrsO;J#XbH{=RBMmpsAOns9&-?!_HB2>RTF}Fl`QX0Trl}5`DK(`| zp)BeV^GvFq6qj$gtH2rQ(Yk|G)PHLDiz z#@^8k%~{BxtbRb0{lg>vTc_k^v^g`qdLS72gX_N2Ck}?(iSB_hiN1n?*X;`S_zQoW zEq_Nr)6;93O8xBJVM>ih7i?F=f+g$o=Re{uS1&MxqB=s63W-lQdAzFV9{AuH7S8NbXt_*dmU|9BR(%O+cW3uniYF~JGO55=H_a9SMK2p$*;$_JzrfoTCn7Q zR04DGQ}@ReE+$iEgs$25v~Tl7H!Zn|yjC3{ihd&eb8fr}+wsn5Zt2>mVu~~F$5obW zee?IV*a^XirZa98A8wspBCyHF(JHL*>!XQg^L|V$teZHi{K_@8wM@5!9&3o31Ze>%f0j^q=*?Uf(He2-kMU~qH#{zcpOqv+OV>5z}U(KV9}r==(tNUE3c zJ-rmt^Z07rG}A&k?+KhKZn9Tzm6}ZUa1c;2(Dbn7`QYGvNS^&$uf?SYqTCuPm4$x}_%Eybml zD|zF>CpP~%m$%^4+%Ek~M(&4|S)HQZ9W!GqyVX$2QQ6S`qVoKol{`PU$3BfT4v@18un?d(F2z9%US5veM#P26*mm1lcw*%azx zwS9Hi6b4ok#Za?54$Q4v|I3Qy_wT+l?dqEJgJK&Pyd2A)P0F(ms$Ko!ap1MDLi#fN z-z~3B5f`28^t9&fX^!{>5BpCUwy@1$lwn%KboZ^^g!11>30XH>`M#*_+!wj#z0~S{ zg-n?*6Jl!ExH~Q!e7`cf?%SJmN8uBU0Rda=EO@nyRhllh#s6`Xxz8N1@Rmx&1lBcs zUz|N7%BktGSBSTsP0{a&#>vBa6L$WrO`e+j_X*GSm~+)~UtV-e{QkRbL&kzSu2t!_ z59HUH7d~lZj7Yt2_5QQd`EN$L0U!L{XDs?Ec95gtz?XOWU&H(v3K+ijG;keT_tIzpZyS@O<~|>H7Z@96q@nl0Nh9uu`&-*5maKt~TpVF&ZS= z2tCLx`k*nv#dF`0i>uyx{Ay8dTg=e5MDkukm&b-6zX^AWe2!meYmW#}{L;)7{>o~T zGgC!?jLpFpkJ8wyH`rJ)SRQMX+|=xIM#byVV*j>+ZxT$#X6dR@2e|zdopWBZ>^bvY z>xq-mll2=KT-;hZ*d8%PJP}D-)Xw!$gfEaGY>8`_^Ue+VFE?<7Eqe5O!%LPU{ku%K zxZPFxu0OedE5Li&JMOPeJZG2t_7~%5p1++&ZAc#UT9YQJfDGV@2YFGnmDJLURP%+@i-Xk5C#hFoQm+@%XuhQ0(52CR zNuys#b8?X8^huhtFKNyf(n7whW^<7C_DR~iFKO==(m5QYb9|D{=}S82g>)|m>0Y0t zd;5~^eIdQaL3+<8>Ak+B_g+ZHilp_|F_{z&_c4`?3MQu%U3Uq4;D& z>C1-l!bZx$M(UG|v@aX!3mY2;8=Fryw!Um^FKpr*Y~nuI#QU;|zp!a=uxa>Y)9A~l z@xo@w!Di``&9X0>))mwzn^9NjiwW zXq0=lkiDab>j@)oMT49a88J^@CK zhE%_&j;^Dp~0YB42E zky~+4VwiD?SjmSYiNYccvECnodPFqE z9oWRO^*RnRt0;(OIWtz6$nJU&cU(23rzH5IYwU?H8W$&sKYJvRmnh!A;BoY@q>VzN zZffG>qOixy!%s7YUuBcJrRMFN@Tx8}f%95|;52uUX)+SuVpinEzB8Rvk*NE|G|jdw zZMA4d=I1C@5!cBN>}pF~eNBYFP4+)os(INoKy(4y35KQT-X;`>NN#!}6mW`>?V8Y~ zE|D@ZP1S_xB1aaHuUU?+j@8YqyTWAlU1L1-En9k<49`@?yadg&Uwj+4$ka82{y(#j z{f=1PQ?ZoH(iCs8IC0j3MlEOaDU4Ub7;l6X94t$Jc`Ywr!Cha3`C4(&KrvcK!dvh0D^Y_V8F%`DvmoJxu!7Z&ptiOgOW5~-9qY1iVA&QEvw z!Wd7Kr5C!hm>qJgzCNQNJovn7#pIy;iy`jP(<|%EJ-EYD@q7<`z}e zoA~~hHgCDRq^a8|C3|XhutiPatLnh6W?P9C^$I<=i01AfrnVHlOO1iy5jIgX>iR28 z+ONetpVBFP(0*ox+u5!D-$Tm+SC#8CvVK`?R`f+OqBZ5TxirsK&Gze|z2CFbLuDQ< zkT433Jaj|D^M|H?1Y<*p<686UM`mco|0sAF!I-t9KRtr+LPYP)AAR?CwD(?O*{3k$ zL?i1hiT;TalYEOyL?2{)z3du(#o_N|SN^LF^S5>VpHVS2wOcxb$;44sWJ~rzU2lB{ zo{Fy;C&OgVh~>t9^$*QWzWnNTRN~a=pOu&2Y9{hD1zJ=~n@=r`WQ@2uwRaQaB0~v@ z1Z9tD{eN%t|IhweziG>i@|&R#BOJ05oTsuDtp7Qq(sI)ApT_Rxj9y>Z1E$1$Etcyk zafsjEu>6OHpv3fM6~3T{jmNKq)w*+vHH1p|%Pc63{~c<>aII^1b9BI|`4?SZF9@AI zTZpMiGgi-R*45&Lj8O}o&(yq>x_Uumo2dxXl6Qft-w6eYE!=-C?ti6>)UN5?5eru@ z2)Y*SnA zoiRaj0mmmLuH~ZcnpdTCL|2?BlkM1Uzj_yoZK9L>F3st)^laWQzCL-?+FL9eZ)w!u zu%2^aaeJig-dnzTH&-A074ZM)uT{~rG{g_E?KtdTbFlF5ueHTd8x4ymt-Q2CTzZr8 zZR7bf>{fo7`~UL_)#%OU)<)tETxN`0mWODGGq^cM$6HEo4UXO#K6`8Q?XB_B+mfTV zrAJ$8?zU@OHEHIzfXBsd`qA?`g?K(V?r4{m|Kzx(cN6P7#-*IajPn`-8?EK@r1iuZ zL|Sg|_+HBQ>fw%spKOdChu6+1$gI|qKfs^&%Ru}9yF%jb#;!eQs~NKzIQlm2{k)0s zh=Pz(qTr%!8sZB$KK<5p3~}+i;&N4TY1kImP9e8clg$%%^Z#<-|DY%%wTJi1ZjH&+ zJJ~1i+UdCepu(=_Lab#8eCw*`ZLZ!s`%~fngX@pPhwVB3oA1nRgNxC7Cw^j#+N1G$ zw!o9w$3Aaj@k-$QQ$6qZ>_b;KZJaCOPpoeg z9h7S?x&FTFJojR()M@75oD6p*9UOPBp42b;%S5X=bl1T%D`!pmzvAc{iCb3n}tl*<1Ei_E`S` z{!er7-nA7nl47#?w@-QDlJ4t|^Q|5z+Ih1|-@RLVSJ>`OeF)F51sb6Yf<^1uSnM7( zcHRFwSCD1b9cF2^KMMrDEI7V6?BV62lFd_HcV3M?7%KY2F=l7U$(cpxJ3p~@Gzu(n z;D5v@5pe2|_yUnPjp5M`WL_OSc)n43+9%dW2PN+;;Q8?I^~&EjL>YMAB-);pd;9;Z z!&_Tf`8^9oI~=(5?r7vMV0CyXTb96n#CFHtMuA;*Zw>#xxor2zeb2kVuEXgI-rl!+ zw_k2)+=KVb^&c9wZYaviHyz~lVwBg5*XlK&aaugq=FYbJ;i~9k7m4h714)AyEPf&iy z_bM+-RDt=A1AoPWUq^2I+8Fa=ob25eZ+!fBt&r=;`I@yt>o)c_fv9UB%N7Hoa5 z4ey}R#)Ly%?Aiu@${02B}NKi1^2p_e|9_2cD?v2-_c8qVILeW>`K>2Srfed)G8L+%E{}quPU6~m2IBV zAf2xHdsmTz(Se|J&mF(MzPY`-p5MOi&oq7gTMbjTFFP}_qd_BKLrXBb?STtkT3?ns zFegc{DAchZY&gNg{x#(O|G>^4+ph`nX)!EpVZRt29w@1@sD-6&!p8=w+$%0hPG&AI z1RAYnmn?7$I{89?+128P0{5Sv>WngzOq%QwX4`ii2CTN1*Id08edwgCxNmAnv;W+m9vaile;iqPAb+l` zN_b|7>xWa;ZnlN|3A%Hfr^mef`7&U^tcly^rA%4N(q`-2F^!*l0+Uq#g5Z;_$GAT- z2p=?9CybD+zUN3Y1*SQ{zSm3P2H`P(GVQIue4&6^*);YhtmDu9S zyy{}!o?zF47Ws*PxI5XE`4UsbHP^jhR*@?c(C^c}YBBZjiIs`U-hW%WFYE}}Y0cuE zD>EnQD0|Y04MKrgYZ|70HB@MuaA)1|r(qnqNjx^6uITvdWatR6*?u{|%y0Yo&A0g3 zuMT=%&R8qp*pg6jEV*CrXU;8kv(mV;;h`)4tvtZ}Jx6us!kKx$ZeJ};yZiO})TXwT z$y^N=GjFCX-m7o6uHoTX>&Cpd6RsQmo*TV9+sEa{Y|aYl9yqr2&yg)WLcUrnv#ut`wMwcsEDDu4qaawuZ1FW>Reiy3 zo;x7W{3>R>?YnnaeJ*={@xt%GIYq8Pl<}0hr*WEs3)loR{=)}cF=M>x97d@F% zBEZC|$Z=O-%8SKnn-&zm_|U(lRk1!=$#$9(v)yEzSpM^hm8`c5Na=Ii zcz<73K*#hA*?l4}<3pZoZ+PLmzUsR3j6-Ty4BlVl=zDnE^F&|KMw3N8T3oLV3oTP% z7k7CvQQk>lPlLPglt|Bd$4|nDlMlvUBm(3l)0;vmK<_hG7Qa02tsBirrvKJu$N zDYfX*Vu>RMkD6_}c-m60uZm?7Qby=>3ImY_XM`bR>1Z-w04 zc6vrz%i)A&1!4~x`8k|q*9tH?iKX)?csK~ZE@;!#PdakUZ~@nA1$OQ^&3vjU4I*E^ zIEcZw z-tZIY7W-zhx|dpy*hePmw0W2MjM2?60(wm3vrv1K-%bQcc@V5|91qt3nW z?3L{t2O4ItJ6gK_$BWg8n%(_j6B;=tZ(@o1nCN%jLcMs#<}lIg2YF()m>G6^w=2JB zu&n-;CHuJJSdL->$C<`t*~?Wc3j1I0*O6^e&eLGz;o2zgY1OL4J#q0~9Vt!;-Rt~c z9yyA=`LN_aw`(eE*@Q#xTni@(7F_4J$ND~4>&O!62nH41rSf0nx;A)lsBqV<;4l3h zJuyJZiHkApK>ga?cb3$ssOX*2nAY)S;j)efm9Gywf=V7um?*VEAn$>rSLg%|BbNph z{&f>1Rm@hmhZbeS&>Jv-X$2}IFJlAK7e9=;# zj}C8r#6Gl`SvPmQiDa;kG=(*>(6lKsC2vpiAduTa_f((B%LeM^speUEIvigO8ay6sRj zS<%bL8f{^=bz9nDciWmOjOx{B7FyYgIdr>i2!@$*$?)o^VLb zZe5C~)WgTKD;^#5?<@Ld(!h1Jg3tKe+)p!3*E};>zw>N<-{(26Yo6P@-+8{C@5=)2 z+7~YRyDs+keOaPi`_gBA`K&8f_Vc$mbN`qB(RHX+jJt5!NuTdaIK?AoTh@oEvRq?W zd{kat@nguImpS>r&zZ0K_@;GFbxx02ru58@nrECj)xsJ0cl|1tuYAgrUU1m#PT~~S zI}Cgs+r74Ip3rLAuvl!u^rp}gdEeTtk4JJ9FzBp%{Ov;byl4D7n3o#sm9LsIulK?4 z#Vz_K+{%>ndSyXCHdpa-EYS>~iOG@eHyn3}G zk-I;LU#KhCGe1Mc!(HM|epav|^UDqF*8`YhK5(y0(0#i7Ki}u)0)M~P|0)kQRg8YT zfqTm58p#!n$%!nQp}EhS1OJ2y?Jl&jPE@kqXv^N1HAgM4Gl6Bdn$UwZ_5+)nssu`9 zcL+&*$hvGMtSrQ?$|z(u!}hOJ4trn|U!v-wvOISQn}0%iylPEH9}CDgG%pXSa?_Ob=N^l|`8?ST_l)m%k`G^))jiL`Z#OF8@S9OQ9f%#c@oA|5^V|O|)YaahjN0 zw?O2ctL4@VmhBlyGtHQuK8?LSO|PneMKzFFB}n*}sQ_!CAlE}%PC-H8zyyhf9u^xD zlpKZB8ijrdC#tErg;xmLC$L0q?8`7zG^C8U<3QM06xQp&g_k>%_|s$Bt@A| z*sk!HbY^+irB*kNq#))+9?HpqJd;9lw;0?wCUk-=NIEF+sf3b|p^|Em68m8#qgLx| z5z));Q^EypJzC}Mn?h8N1-y76VDo@aCxIpSWbNkyw!jB$i5~rX#YMk&{FljAh@SD- zg-d|xegSvGwaS$S6Vozz+qVh{IdFaZ;`cJa=-?zdg@Cf`o6}O%ja3d*iri#9C&(kz z(8;ebE%CWx!%4TjkGS&+VpTO~p4r~Dx?+mkkHD9k^nPp-d>>>KXsG{HNO{iAm|uq+ z|8BBoG`6ivFgUQypz}yo&lmSc&W00MSf*9R1e~nBETGnUSyYeB`;&ur@{6h3h5f%( z_?QkdvuP?SGVr}@;AWVat9v}^sHte%&1p)Wy5|&_JOZpF9p=sqj`?doDO7QiqySfL z!i=>Ib55O{!|pgQ(6RCSMs9D@ncq*AOzoUBJ<{6TbjtC=*87qt-#4>SJ`s36Y+lU4 z|2F5CZNIu2>`(L9J+Vnga`uFZnV*6uKYg5VRMPFm39;xIV*7VWr);c!5Z-@KocBQc z-0*{}+@eem9A$WJR&JQUZIiIr%&PpD@$`H#mNLl+fe9QXFDp%}7Tau){-`$YQw^vxCivle(rERm^N zx<0Eo_^X0}(|=Wo)ZCaXCAp`$+LEG=zZn!9SskdjT60rS)`JD#Lp>Z{D&2A|4@?ZU z*edLPH2Alrn9$cLRbFZh=~M5h^S5lDdjEK>dR1kYmvZKYI{5^)2M<;pVPb4zn9wK5 zHZgpD*uwUj7wy^K8QMPZGD&vTXsnkoS``+!>e%9jn}zFM?h26ST&ms3ygPwC_ygPH z4V)XiHrl86$UKX=kh)qSBjH*{Lidzd|0QvEzs5e?8uBDHZt0F#mDh1rol_<##D7t> z-S=#nokH)Qr}1*p36jPMtYrzTX^HoLG-f^7l)^GK){xg@cQuO(ud?TyNABy`Co;}B z5WRH+>uas{qX#DZV9$JY;6Kj`<@t6B^-h}@JOTntCf3JkD==oyi-0xw4!kVw{XCnpmr{y+lRTHZ=QJ>{z)i>&-KPU1HgD z%hm{3wHyw!X*z9vU~$fwFv(-rcHV#1a;0syb5fsd*V>OCw^Y5}wVr$T#@BNG;>jO3 zmOj$jy>s>M-O(GBJ}}!~D1ZBKx4pr#J=uGXckem5de7<8d(OVzbDn$eMeV(pz4xBb zo}LxC_vUJbEz+gI;iaAhrC%nL2EH`jG23oN0r$(@+_eu@F>YrFS-?F_OP*VSWtYGn zw+_w&;_^Zh_M05vf8aVp$%K7d4OE$GxLNl6m;3+Qh|%VN%&&bPSL+^pwC!yoV^RV4 z#Rpqgu3mhjx}>1Jiqp7UI<@=)S9OiJXuUae<8{%yQ5EgeE4tJ7X)`j;FzA}-&izE9 z{Db!XHPQRO&o*joIQ)T;(ZQ$Kx#zH|19Ni2fruGLyme&U=2&^GIl{N*@U2UX3j?_A z-bfzY#COXeM%YI2=*Cqp+p7%4Yt27Z?ax}sJn5MD^4aWx)mzmU74WQE8!c))huiqz ze!rfo&^cCLviJYsTv^j2;Nx(D-}FQX&%tSBJ;F~JRyJ4#I$BL$y0?_=ke2%FE8BN* zG}hiKpSoL6?6btWqn*c%FES(xoZt#zURc1rWdp}gMV8$k{;Ev6 zB<$dtz_i=pq@){nwgdMh2iENmICnRmUN=Wv*5J(1nlmT=?AtWww9Do*>)!|{I&cRI zaIF0!RNK98>mJR9H!NFnP6u`G+s;sPIp^RR9`WGW`(DeO-W+o}sz%U2;M_cebG9)j zwmwh}*}(m_=PY~SS(n9U@4Pw7cVYi5FK%AO^RIN~x4m)i^r_39uy0F3^9z~tCWhyq z<(y|vWZZn`RLg`4p|ckoZBG36Is5L9+_gr_+?Nc8K5^_=!1r&B+;wjq_3VMb@usl^PYH=6V%vJGFf7{3tk;|&b05U}FN_J8re*&#w` z>O=zRKqaR%wb$vH> zF}ym_7xl5PK%jq-&8Y&z!$%sJR0CLE%vD(NCX}~&_Qo6|9s@R>%2OJ5H`q5Yf6Hb} zEMUIXdq;TFO-TptdV|CDAD)KC%|CaCHRs*486Vi+@4m^wc)>y7IY;BuHE-{yd2&mf zxL3XIF5kKXlVV>q*sU+v_+ndavq+uPYubOx_{=>=$&hQ^F$fyF22dOIq+6M*x}ZnIhX!O zH?Z7iWm(Un;J`ht;nm)#7km@uIrDsEI)CAa-A7S*j%gQOui1N(!~R3H-;1Y`H|8m@ zUcY+huaC)kzWs8G&L+!Df3WwHX0E9E{7>q0U;m$T%25B4B>$(Una^!5UNBz2|F6x( zRdScs%-Pp1^WoE)mzG|yw)x#N-G9GU?#su(|E@P3Ov|?M-Fv`z;gO_*g3imk+WQwV zoSjr@?0#i?)Y}=IdasNOe>z#t-zl`PGFIZ1-V8a>KS|eCWyY_`eAmvRU%2XB@vSxA zla_DyTzhQkY>(TsAGohLbaSeo-(hCQ!<7p!ygdDrH}~tmJwNB%KlQ5fxrG4NWQXU6 z178RQd@M=eTzLOy?t?R`mww6p|5SA2!iM^bQiU%+aWeb7=lqfO;e4*1$@}Ac`k#;T zf3<#Jv48%)gZ-~{{vX)g_-B{>FNOY>jAte^uKOeCdt!TEhD7e-6?Zk|(lvi5X^nY534M-;7hTW9O0sY>OnhRDN`d7^f}LW4BgeT2$cJYi;;7 zrbe?k?QEN*u;)U@#T`d^I@=s}Tt3<~%S_T%OTsZ&#j}<7h(MCXrY8s4vwkUrJlyj5 zXpgk&zSi9Zr}j+al8{(DJzRgU8~1}VyH`9oye&@n;STPf0!+(d6s<4ZdLndrsn}HQ zVv$9wpE9X!jqsR}^RtNAYWlSUA6Zhv&$abW_29V5#w6>#K(qVX1F3B}x42iVv6E;D z6TiJET16~x!opUi?Lm4c_UtT9I5|!2-#YC%FPtx2<9E8=Q@G3J**U`?&hs}nzyBY5 zvt9hS?3`(zIxWgBF1T!wSUz{Iu>TkSg-3&g{Ka4W_^oI4(WW?q@poH-$KL-n-uYJF zA};H#YY|(KB%3ZYxnWA7PNYId>4}ATitLL8pRalEqtdP{>9@w)Svvnn;PS2;T1kty z+7)%{tP^Tt6qMShbb5`@v>2m}vm>H4nxwcaSFf>~k#k8=dw+CS>#})WS*upnG%Q&+ z`-SjoZ544ZW6uqIL5zY5bvdv1%e=SASSOX=;Uwqqi^YXg><`nM1^f>(j~EvOo-C*_1JzRZL`Z|FW;xVE?RBY`j^q-C2>4Qy#e$R^V4@+*FE@Cez71)t{y?X01?$Fc|VXboA&C~2fUVXJz<9X8` z9cS3-(|B~x+Pp>H$BSQVv{AYZIyl0|1r>m;i1VeSjV29Rd8_wh|{RpYDgWXrsZs+y}?`V|}Y%$Qk z`?Jj1^zGK$b=7SD!vep)6^lPquqb~QCx28_OOA&MkMe>Asdsl6hAv={a+}f9CS7&6c<6Vm99rwF@iRtt$R6M17{7#y9#?B=z&t{m)mRhiHzis==Wzl1?2YgYsUoHxI zHHz8xEcm(L+5F=_0%O}M7L?>o&aeG)_F}F_P}CcPL!2%vX3PC*&O2XQUg?`}^L4w> ze%3jqYj(PB7CGR^UhRD4Vz{%@7Ct7S3-MdKj#>b>C4b_0v(61g1OK2CTyGRu0lL=|A{R+9RigKB8i+HKV;<iMOi`m<*L}4h5g+N_!N~p=ls-2VQJjqD$kgy8N2a8;6j(DH5w_N zQ3;F0pFI{ygE-w<&Dy6;8fS%T5~}37W>S z(c$GZPT$NtFQ)7ls#QKW&qS>H6tgwvoVdY7cc(wYnLFtY?6 zU|Mv-aQ?aiXja%(Eguj*+kF)EFE3DbshBW*^`@)qvUy*}b}#bX`|axbde)o-R_lmO zT@TppS6uAn`Q2P4cx|Kb>D39!zavhCUE4JMXil2x?#Odx*EY{*&CPJNj=D7M+Lq<6 zxmlsRqpoecwsn1LZceIo^vzvUW|dRSg^9G-Zzu#;7RQ8rtn&8p;L z#9W1gGP55tb*-v-s+0dy;eU*Kac&R~d)oo2>ro98C)S9v+E||Y?@`ysFJaLatC4>4 zd$44;>ZFOb-+!Jts<2>|zgufY&tkEP7i{ipdQx?ZD;1mEPRyUZW`pPSnWj7mTNW$o zzSK`vIU|0tWP-!p7w+y-%0+%f-HCf1@UM7p?e{c6Sox!H+(DKeCGGsMjz>Wq|DLP4 zt zY+?3Xz!#@;k+WsRCaWw*X6X$-6+`vDGWpH@*jsMXz@5>^-L>#V^-ifLmWKZ=4vF?n z=nUUelOXA#D^c#;W-asRVu8Xk#Yvy%_Om|K3g5z1@Zg1x43o@6HOu3+e1Z$L?>-ki z&LL!?_mx3!ub6MW)yji1ciZe`UVEkQx*RL}xkbO`+U9ARZUwd%WA8WIH2a;;(avUE zzW5fu_nao-T%k_u9gS?J29a!k9=MAA`uX0Cqek*^-&Dy>7x-VFauDy|@LEbGX_{St zk}&tjWqYQ7-!JcQa?-MhDvsz2eDOTW?q3tWpH@%#l(h5}Q(Xc}<$}iV84^t#4>pLG zclbWwSFGT?9MCss%8Gif!~v-y*KymIAp(QqMhgI zeN0o9{||0p5U~ypHr(xTfQ`i=qGQX~Y`gEx6Sh}x+#$TUbJFCcfs*gKCeK-5IAv#- zlHuePPTiBNB$sjWh<#aTbW31DM%Q(XnVTep&rh}%VbYgMp8Uy6sz2bMV`OKe*UTA3 zj#Z1fTMtNy88kI0PciOjTF<#dpvkzH7Dkxs3+qjs zeSr6)9Vd%@amL|bXO4ft40WDM%&Q#?TsRDEI!sy&8avqH3z{{Rx{cN>-(}&@Cc)wC za>TlY)%CLa_W#+IL8}j&x7b;WaJt$!PdI&~ris;i4KpK;rL~H)@sf#NHXYu74jF7| z`}4_xpXZ>!9WIXQ&Li3_vu;e{`sB!JA>4Yx=9A-*xFcQhIUO7pOvTMC{68iYy=Icz z!e#7uOd)3SV$JoNHf#{ya&+q@12dt0W{)-=c(K;y;vu2QN1IPDxGYw$OKQ*(XjkRh zP~_nJ_w=sdD@R@*K5qHP&eO-LvWQJ^gAqrhd&8sU4qJ}*Cn%IM^p*Dd*ZV0 z(&o~H6IBoQm+~z5*zI6G#dP-!kM=3YJ6LwUzkDK0=fI>X&J$Zas%$)&dbTv>9Iu;o zbo=U~J9oQIcHo?PVa5UntwsME7V1W_c0hcEA~9L))V&Ts6E9h7vR11505>IXO+tdiy+VboCy{w z8+Xp}uqoN6VbH=~=@8*@dh3(M0~MPryg0ZUnld6RI19WR8oei+Io{^rbJXUv=M7tDWjW&4~OQ$NwWimbQEXDZPA!hbjnauc=n28pR$f-uQ`nPe39QfBKR!jVJj$&Aid3zqMaeC}gD$xu>g$z3merfe1X(RL@%uTCsO9Cyi~%hh_^oF&nM<^vxUkPO_pZQg?3!_2@DRM8WP@mb*r|Ev1_n* za^THbHr$64cpoWjtC*#FQAwxjobalNGEob~sub@}QIy)GD04|sZc*P3Z6`$~r6(?n zdN}r~6$z&HD!H8D&`t^~zN@t6h0=}5yCr28s~y>^?z7l5NZI@nx5X`i-%=J0r>2Kn z8@oV*_j+q>m$~P1&Lo5!msBuqf z_Pr4m5wWS@a_I*)Ds8T)lHr_3ov+ zYmR#9^G50)qW2!E-g{(v z@3HH>C!zPArWzdo+keliiGM~r-w_V;9p;rCtp^m=$#qX?V7zgn#CX;j9kw4$MnRs> z{=3GDvFe|jv{CIU=f|S>vzt~adaTi$a%go@gU^EYh!0X(E4cX=H2PHB;aJ&d5X)Tf zW0%f^rgo0_b5#wDb2}`2?sI-SzEYTZ5;QqcOw4pgrTk*{THgy~nRCeIRo!(fCwCr@*0$n;JIW5s=}2C??m#IBjOG zM`A}sBD1&YlLyWm2bxV&Z$&KjV7q0KFlSfP!^0MnjjT2sYfhejie&{qqou|HR^7|( zrr#b}PBsK4a*5ZZPBdn%h>Bg`d=xaR|(@?pm>X_isLpTf61|PLyG?ImqmG$k^t{>1{`Y zPaCdXaJ<{*cJ?8`6?@bU*_?fBb6)tm>ZzuS(iwYacL+J`y^|Pr&70$Tb9lo%+eW+F zn;tRhUfp~D@m@WSeLfq)+y2ksepr+!k;n0yo723wIZ2I+H^<&Fw&QCy=Q6#CpPL)L zcwc;a`@nbQ##hbVQu74f1h4aU$r32#u*hS!O*s?N>A|$beVN;9-dKlskDqV%lNR4| zQt-*{IWFCTUoMLB%;H;ceM`m~Wg8Bu7Ok607xkVv7&GPAl0P%21_Vj}efXjzNO_9m zg1|$Ss&CdrH5fd&XH&>7IHSq6lOfsRQQg!#8H}&|LR^b7IIZ@!wtRBh{^U{2J^r8% zr-eM(n=d#wJ~$ly=Wqnik&C_R9Q*7VCpq8a4y`tbjf1#1HO5_~!mO`4KSx_zA8+5+6tO5Emt zY|f}T_4JLeNny^5E!hv3oU=UW`Cll(`eV1u?TzPdwh8Vt5p3g*x09@p@!Y|~Sm41P zldwN0`8bo62V>LQpO0M~IZiZQDQJGPy#KD=!+nXCQ#|>^?>9xidsdfsWr}_M!a}_- z;z3W}$@YhT`1h{=Xa4RRp2z&m7chC&WeA_!bSinusek95 zNy*My9n#I{uPru@hkQ=V4lT6&`gv=P;nR0a&&u+G8uD&!%X{^|?2FCuci)~AzFQ`I>r2sX zlS!r*eINa~l`?0NmZYDW=DF|3I=0#>Xg|geddsuL=tfirF8yDA6O?^5Ei9w@JIwIuvxf6+@df>%HVz zW*w7rQIkD%VjqXb*CNfot75M)wQjh7{vW^c0`{yAQpq0f_l)<=f44rQH-xJ{$uVKS zk#5Mf(1xmg&+U0bUVZ%$pL%0^$G)5bW;u@M1@a;BwsP)0A6@hHCYGnY{GXVX9+x~r z{=2N)HSSXjcz+f0Cxxfoow3kKG2^ac=HD+ZE3QdB+9}d?O-?FDp@}75caf6s*X1(d z2d%40)-KYXwP?e0C4HquH)elbt-gAmToOzE!}lBFst(+fI{D^oTrsnC)a0u_>X;fW zpL6u-Mp#`+o_aDuIxl&-@6YWFvP?$FGyMM?er(yKQz#hlP8I2Zo!Y5Ko4T#38FKkxXVTh;OV+4g_0kJs_;Y&^_$r_G`9u+aB6 z;{QMXSO5RX{Qqb7|6juYe@*}Yt^EJ@`2Rhs3U4dB*>BB?eC6YPGOMS|{ur>3xlvp-Xv>TVj;s5tpr}Zg2!d0o*Io;EWF*;CmsEHz<>6d zxcy2o5154lI%4?sRye9WytXdk{vy{&=lrIb9=*WZ=>4HlFqkoH`X*M@iX|&O zZX`T7*!}a@(oBhsNekPBr-xdYq?|v-s-7Iy@nt>J`R?>tcCsd=0T-tB=IO24^&n%h zY?tqx4)KR?O9IoG|GWQq(0BX6vDUt`H4}dvWJ}`Mm|7=eHYvx83Gs5MjY25g-D7s8szy6=ohgXHi?Bc9na9CG{9#A?b&#{!@T;3PO83|!Y z6PHddzM$E0mFa5iat4lzTbu+qU$!)IT0Dwbbbw=q%jQ1Q?g`%-Vqd2;CwcDl6}ic> zW9{L~aoXE{Tw>Cy(C}+E-uYd!U*2ic#155N9Z89y3zFST9$z_hu}Ao$iK126%EjCQ zEQSt8CvSalv3DZpUXJ7x-YYUIX!b1 zJdmfN9RKOkF6HeH19=(UZFE$gEm|$3yG6ikVX0J|u>|L<4@#Yaeh%%;`eiK-Q`@*q zCbU^hYWdizXRLFv&F8}wBmgqGpa|rY?F!@;d@J8zVwG9_s zr1w6tI)8^D;dW%c?@Ft!7ZRKe-5)cginTX9&W;EQ&i#5QU%WSQ_VbS~Us)wrd-@#P zddrh{aUcYSe#-AT;grReiY!qMlXZ(-(qB7hCA9Q;*t)PzEa(V0 zkSbW1dWP-Au7jsOB}fX-Y4!FF5ZWna!esv=hpR4O0h5(L=YMO^V8n$mwm%ElhWl$xj!*Qm~Adi%B0YK5?`9DJ1C;q`qT{ zcZk8xl>t?s6b}61b!uCA+J`G?GS>&y=^?Bhj$&;S`7KkmK2GwOSo44KRPF$6XvOJbg|p%gwD}K2SF*8z)dD!77FSrpS@?KD6zD;Ma4nYWyU1wA_rX#b74LW z{wD90N(Hl4HY9VbX=GD~yv!J_>k+l+|`Tr4>;k5GIo`!z+bjW}k9W z-nz+iU#EW7?AUW@iG%P&w>Z5iee2J8M6|~=$~y^mC55Q&itW^s%2U><-FB?8)iaaj zuxs4xN9&eyF(ie=c^#?<^@xvTT_oG{;AYLLhkK1{Jy^`lHhDN4ViuNmIJF#(Ak)j*q1FNy?v{VSH1&)0gMT{{&J_)Lq6%rPPt3R)%liW zT0Ye%-Ei~hYSqoP=hi$q&!~FbVAIDb-APaFpYZpc7E!nS86#-l{!@$Fpi%MOiiXOf zXHLPs94sFeB;Vb2F--iBcVijznyR+zdmanvvq<{P*3>${W@>x0Uisq135%ApeeH_O zbTKok%)QLsIf02c<3g~pdeedO7fq}Qrxd0h>7JRJS>X4T>){_U7uJ*OK2%I?N#xDH zp>1}0Ra=wi1eb8*qY-~oQr2kQEPZV$ZZK#2rd=^95htqe*(5OT3ZDAtV3Paxq-9eU zzx)-o?nVZYMU2NM z?%8?f$Ku?>uh$4nnjLdKnJ@l?FyD(~&t~7-e)esi=f&F!f2K`+nYbm}vhU6;nX8gY z989i8X8tR((&oKXVBvb!F1{>Wr9`t(InO(S$LVqVRo95Et5mzJSr0G>niOoPUj5?R z{uisyvUWP~ay^`|ZTDW5<9E2XnHRlbbWXT=*3CdgWY7JYdtV%Lc5Z8tJ@qzB`ACo3 z(f}uyGc!VDa<%5XRE}o3m^btD#=f%$n@x&0HRy6kW-dAJ^Uuh?tKN7jWAuV2^A4MP z_sZYhF+czB&iME#mzT$BtSJ9kHDlHPB&S)o1lHZz^t?fTc1OkGlqDT+&OEQG&XQt@ zm|tG}_Td_Vd()47x43AR8I(8w_3cmk=kz_8!}{k7l^1i|-;)+HdH&Z2(_rP-Y zhFEuJ+xxzT3~Ov}_{m1QF^aB^o#E(l?@8_~#|XLKOB+oz4zkZU_`5+^uA=v{Nb8%_ zX6X+H4ox}m@`)4omIK~f;>BMba?1&mxZ*nRtV`LCGykJn&VDBTNizL^u{uY~j5Z1g&^;J@RV1ALW%A3HkS z=0%8=q-;|anf~PpZ^VJ49}+gP%5DCeASBtiv!KPLZ-QuT8^1!6$OjdZX$M@`o{H_g zAilGQ^Vo4=C&isRr|uMVVM{o)_{yOVcRBLTbcy*cW!==$$2z$yL6x1i)5^e^cay8w zI_EE<$0DXJJ>sJ}h39_S5zZ+cF5ya{;tGpaHgwK-!MrRdHN`_UH0o*Gf~8SHYK~HA zM`AhGD4dnh@N&J8nm6M%v&b{=52u1@#)L%|o9@je>nCH!vb$WV%$>ho2p4dvw zr%WP_Yh9Vv3AV8O6m*pEQ8~fbA$Y`HtcBBp=g5R(wa?Tu6;vE!9QLnB_tBE}6}l%V z;&fc(SoO78HChK)I~Y%<^tAj7_sDhO&0$gAa^|sVV#|b#&S&f~45v>{ebJTX+O;X8 zWyg!|Q!Bz_d=nouG@iKI^Xf(4r;L8J6P;h6Vt*blzM(ud>*chf%;~?DWwW)02&I_SOqo7y#f(iJGiR*~T%b8~-O7G5 z2GIv>|0AcJnSJZ!+(()7UcH?6DRcg>m-Csj7I3{eWJ}tVLR{78zwNwtBVL zDQk(>t0h5MOQT*bP0Cu9^=esB*7B-X%bT)RbiGs4YSf^0f!X$q zbF|!!- zW5%rDb=gOkW$nJ?tdqkOpyTjg?aX0;1C9r@4zTAO-u*1wQR1LlPV))7BZm)l9K6() zxk_Vt)%9>goij=t9Cw-)yW}|ftU1c0yLwypUO5*QiDv69uWeQw*?WlD*2lTrpuup% zn=cBCn>rXKoOm<)nvSU1n{Gb`lP@}se{wENdb^Tu?OCVfllxxZ`t+Kq#qn5P^Ci8O zE8kY9gybe2dbYeI)!@dX_6PxHhsNbsoci=!9;kJ?M#RR=i7J=Uo1$=PrDs!n5A(UU z-oDDonb(|tc^uAXSoc6E?}ucNON9G#IXy>*bx-8ZUUyo`QsH6z#?izj@#ZPL74zQS zS*c?i&}{f1PeyChiUf5$um=UzE{2f@-1F!M)bcK zhxr*qdhYoD=sWzQiR*?@@b62)-2rdjNEs}9^XQ2zL&rW)CJdJ4|TmId1M*>x! zaW#4w{%{M|VlKNmF`~0M)Pf;2Mm>2#lhuFpm*I|X+`yCFuBq7Au);wj=1^|QVYWF1T+ddm8gJ9EocETz%d(QWMh7S5=Sq6SePCU6m(9w>aRbi@!`C-%&Y5LvdxVcU=&+NK z>0u9})BYxZnB;1jEh8LlTMrmLpRBmxmZ|a)jqDRvC3kPEE3)0ZNlQSt>czWT>vEM7 zbnG|hT;W=uwxiIZ|FG%;2hR^PGVKm;%#nK|_QA1alYF$RONX<}9akGClmAXTjQui< z?Nd2a&iiYrAIbG_)@pIGN@!~E`Jx`}>MnhxXNI&&xTKc*7Td>L7B+2UGWoD~p3X@& zon!OX*zubP{x`B{YF0^9Fg%^Zl(aF-_nmjdiw;IN;nf8}?neV1n^~PowLP{;sB#ggRXbvSK-SBt7MPl@@%{w%E}y~>-oGSL0C(o z{Ef{YhZEP{?mc&S&Y#yN7u@v23mm(zTK#a65xL+LE#)A4fl21{R4>h_C+oldYqgP@ z5>WEZVhTs_K@(qx2BvTNzh|jMJ!Vb!XUTdWG1*AR>OzCdhR_!w?_J)kj|iUn<5JUq zp%20T`(FBTe=GW~DG`0(qS{;Ly>BlIwFn+q?Zsij8vHiUxqER3v+|U$_bz>~is19V zd(+V2xyOWeoeW1q9CVClntxgLJxg9CDpt>Yb#YC3ew8|lN@T8D^sucUsZF zwC}r#Z>rfIy#(X$&F^3O#k-a{SF}d|==xW@$LrSqOU{AuKiZpr3OD%tyM%f2!TR(*!{>WYU|r}TEXhR-zZ zPLioIabaeg-lJD}=F|KPlb_)x4argux@Mb&FZP`}pUrti<`jAM+-6zV=P$QBeYsha zWmbJ#l#bm0y!9(w-JJ4wrRSGv9?Q}>UZr!QOXuXQHI7T(oXXm+ncA+Oa!@>h$ui1$ z(t3^THJ_hvoYZ5rYl{AJ4+F`t3lq=3SiaQT<@&`VOJB3DnBJD4&|y=w@!PzeB@b54 zazB1kb6&xUUwvU017=>TdbYAfTKCebLwd$*FFWa`XtQjPc*fN8ZIQp`WLK-H@7x1A zsseO`{m#tLmH54U`;D>?>&`R>#@hFe7q)ENWaYPK*L0`2h#OY(nhH5r=sILK-ahnJ z@AIb#^P{!yoOe{P{PCz!bXv>%Gaaftu9Iszz20!F*6_|=y@DsgeMQEczMrgfS>7!y zShU}nGa$#Ky~d-1#bzSIp8vCIyOetyG5^1?^e5Sr>#gTxXqX|973eMcPEOp{Xl**Nt55!&C>oPi~o!;4F>-b=A zaZQM;qwk&fwLf?5-LG(*d(m=vmWyn?ocGp;-+z7Z=#9MxH`v~lKjYnUW_zur-Qrx9 zJ9+Qk<-LFO`MsZRYq8bLW9*aIKQq>zn`3bBe@?m5-5b3(ocM3wnX#V7^_pz|M<3s- zS6;OA9KNxJ(L%%MtHl33lJvFHLp-mmdF5Q}`cw z)bpvkSQPbt7dVm_;b^sk(P7Jug$)Ug&0G>WhVIH|O~tsx6avG$+j^7MDr{S^@TDYw zBTM0rO~P$nCOs^kD;}$!>=1V1l3F6Du6ag0)>tg#$&11SH}Rukl0BB2pZT&Xx=*vI zoRAsJ7J6i-=jL}Q9T~5$^=fbHo6)|EMRkdkJ9l`PH;0_OZFJP0{v;N`~$huVe3Lky$uHz`dPW&T!R`}^CgJo|RJxpKCSqPr_=Iz#^J zrQh9C%e>C?OwWZL0gDb*8xGNDr(gwtITl%#iY z9W`8L#QEsc@%2JZS9~qFxgO5;{-Wg(V$6N&vO;KNXwS+PhtQ7;SPLYUPnA1v*?qor zo}*)1>6MF{H95ajWZVc#ih4dvI)y>~M#jW53}U6{nl{+))oS+GyH~)|Xwxsb0KYv& zi9(N;p7^E2!RDg$^^E;*AQ+2H_aW)k`d>Qpc$n<}|LC5% zpn0lC#lyDvZ`1EB_@BGVF?OPwhZCP-aH^c(1BQtTaxV(qTQpzHTy{h_IOHOex|62c z+!&6auhSBECpApj=CI)zf5$3=f#oZkMC+e1P&nm&Kh zG^c%5PxU*q*UM%<+WmRkGADsWACL0B^DW0_m+lV*WlJJQo1@ZN!|SDje=$y_qehLt?}(YmT-Hm)@JY8 zDg4<$bjAXS!h7qw8%6(csJ=0&)~Ut>bWby`agPfYyp zrl7E$wjHUZE)V7M@{mUM)qEOKLAxM4w8*`%f?&2vOVMS2*- z&Q0JII#GPe$u3pxzuSX@i@UyiIdAHmaJu`dT6^U&A;(tL{Y#X;Dk*ub;dmKQawO){ zz96^EE@s|5BlpDy;Y&msnmuj3#Ds%iOfS64AN$L>qgW(?xk^(ZQD{rLlE&4>nzyUi z$|odjej({t?Zz~pNq7dokRq$pg$1b&dz{5}E^OHUMZ00jt;yE6QxECBJm2v{%E{{J z)5FbodUy;vm=%2r*i}nPTss4n*%_}C|MOPghMOZYR)*_h+tuO)Kc2j_)m_D)D%acj zX!eDBK3iOu=4})diqf(TV3}zc)L*8^G41ynmkHYrItmv!30r+pWzI{|6kln$+VSM! znIHX?OJh6ww1(nt6*{W~7*AXB}F>!0n(YwL<90gM`9KY!4Dk zHfX$#w=FxdYu&jS@qxErHwo-++VaWqqR>-wWuw_Hw?wC=MJ>Iw8yFDR{#E_VLxG( zy20hSFI_d&Or$zK)L;0R*OTyTD#w)t0+lbiAKVz6iTu6Jh-73+PKQd$1V_I^tAV_m6iotpUAR63gv^afGISH2rkj!c>3^Dwmzqnte^W!7^2H_lT0}B8)+t3a zd<|qxGg0Q6ao~vQ8IkK!`=_m2%=>2Df=@GKwTrhpzWq4aeV5Jok0+($0;3mvc<|V) zu6WZzp(EL^4{5mHoVK~D<*4y8fpp_HD^BjR*_;_%D71BD*bJj6(PQtx~pB@?!=ui2!`{UA}c^WQ1Tqs8kWsEdEIDgi%iCYR(+OdH}$&9YLjQptK0foC@wLgcGceho4+3u&)C-1vwOc& z2*a7#_r7lXzW3wY{Mz@k@BjVweLtgIK_ma12dw5l4hqgIXw{$dkhlEDVMV#ZPX9TN zM7RGqYB;a3mw67;lQRd8iQg+Mskw7sN!{{9;Jl)#>*qYxE&q8s(Jr5PhaMw?fP=uM zi!9C34uV$w7EBcf+p5?Pu%(_nrkZuHV3D-!%g^7Qo&2iXkX+i#%)sHWv~yy~hBL%H&u=jXmF-TwQ`+`!MX>uv9|7&M!f zJ^WnBy@1W@L8Y+5h4v-dH4J_)nr_c5Wnzp_)jOH>8uK2qEI4eD^N}~&#aYTyVegiV4H*~p z|NOb`vHv;ahmv}62C+v1R)62FFIu_YSvo(;W?%AoA*OfViq1dW!~f?<{~tU4pAs7w zWj`<~PIx%w{IePT_f!&0pXD;VaA1&i5Sx|%6i_dCUz7L0A@Lp)182uW zmVySEuzp6nK86(yViga?7Jc|+N&1rlqlSXiCCBG!=e{Hbe9l`a(ezMo=}VEX zYeiBGMOg#>{o)mCPW-=X;WLK^VyBY+e)E^@d#H87k>!$uSSsJeFnxv{4pkNW-%J!` zmnn!A<^4Z)@arPQh(md@2Nd-*1R3fKB|OhD8Z?S;cqEbMC?1wCbGP8bD%UAZij3a` zBJ&<eG4kl>!VLAMTyf6D?L`EKum3wLos=x>3g54iIVil2D!pYQxVrUeTB{2z!cU~T4OkSbPVY*2AOFL3Q4+sn0I z_w|X@PPnHs*(iU~{RtD;SRB7GEO_JfzfdRRp`3m&+m2NAy$7|L4hpVzkS=Nbwdh^M ztRnUDj}c*x+SYm!8o_#34~p7+R)4ux=k3}zCc>hfmxNwz6x_bf@GhUx_fJ+Ejjgv9 z8|kP1{B!A^N&{bpBfnh(-MM(VnyD42W8eA_`>q;)r6R_@$rFqmpIiL@mi*vQ z;N5lMm57p*{s!)My$p7aFEkWn9M}E5_ul2>=6hjAk!%U-OSjxp2>omK?j_5EVAh2D zd3mx6954M_|0e8Gc-A_`eG520n8+Sd5M9*xo@s&E^8WiV1uC7N_^(Y-Z{93@Qjy*1 z?c1;tosCC)TuUUQgLF$b=q`7%iu~fgv@~jE=zos~(pic;*AA$>=oNgQ%do9MA|rt( zOXLa518r@7&7+E@Nh+1~H-E(Lzh{eS4A=6WON+EVA;hK>s_{{B}g!?f+?6QP8gfyt+vl3BxE z8C?7S#UyHVX=>!QRQWuHt_3=45(O7sjDGLSWbkm(ldF%W<;h-J_)=@LXKEkc0Y@2^ zh3wzgrgv`OeXJD!mACquqRwu=S)bN%>b{h)QDkRfFe@#RopniY{>8+PYr}k}GU=`j z7r&Bpl#lnSK;ZJQDOp=s>=QZfo9TU8$Co-SjZq=>_@&gp-|`u!N9i8$U~OOt+4kP! ztYm?4f#mi=+3$tY;?l3QzI4$H=FfTSOFSZnSvwk49@1j)J`eM)RCBFZ^mjs%Z zhL)E`mcO%kQ<`XAmReqxxxFm+ds(4*d1-lh<@WO0@8yl=6|LnJo!cvVzgJ8&ubf(5 zIdgmE-0zhO&8wD9uMlV8n)a}2y}9J12MQ7gxKNs~a@cw8Jv}hEqXe`}c zHQ8~d$I)u`9SRH)4U#{a3@w^XE1E5LG%wbP9a=Y* zOBN+I*;ce=?r6*X(N_4QMmB;oU_ra3I_nfg;bjT@(;Vx?53}Sr)`%;!X*?7c(`qdG zZ_%~1qHE=juC)=n)_iYW-N-8SfVb|UVo*f=L8Ti0MNO$cx-MGuUajc8DN(mNT=GtX zN3R3di%y}Wg-L!AHGji5F#YJc{iC1Jasq4Rgktd)YxT~lZcW@yOebzAoS88}(Q=Y% z+_6c*|o%XSDUzk@Unyb(F>r5ZpQ55O;TZsJ1APl zDzbwyEFgjX8N=e@@`z7d(^eh0BKA}G+l~o+RsH_ER?hv^6kN4*@-o&(jLSx#ezHlu^Gbr0B%?b2IuYZdn+wkU>0yiMC2!AC((s9evj zwC?r8rRN)^d6=|IRTae+DatVwXDPDGXXLuW=6mG=pVuL;qDSgqRMgEDDcc=VZ#bl| z?~?eT13V1JC#Wq_vU<7YYW3b~^HqO;Y`_0YL2lMM?W*N74{cX`v|Ro<=bOZ8)u+BC zM}rJpgI_Gly>*~kM^Q&d@%XM}UxkR1r+#gC#4_U=kNSZl!FDhA-mE@s`DayV)L~JD zZ8MYh72n#&&$M5D)(+05RlKu0bKDsVp6fU`c*rz}|8vLaotG<)BkWBGGLie%Q8)vPz^T%vrZSTFlT^6|5*vF8lu9=^N#Wa@5(1u^{b5{-F+B)Z?DpxD9}(apfy_$#EnKeOP#T;dRfRSyf7ZDj(XtIUZ+t z>Yuhw1OKIc>oz6`&Pw_yJ-?GH{+%u7+4pvzQ_CN|Z47o$l#jbzdG&vqrcKU=x!XVS z%PR@lXDU7TST6pRw~6IN+~>^yjy(y|FB+v5seQ5iE2=Y3;lKmAf|M)r=~pD5KV-D- ziF+V-=fL{+iK1Q$&e#8zNvYm&Q_d;qz{SRN?M;bBQUA1Tq9+(gD}^jzJGwAlVu6av z?2UH2H@|+o;p~5*4Jn!eGENEcj0Oj|MIMScFe-eh2xvHXWp41~Jqjrs9oSdsbooq8 zT-dN+QSkClAt42c0>}C%vnB1AQMkB?Rr|*rBh?Q}oIAM9Uumc^d3#LeOW103a`W=@ z^BtPGWWBbmxVYG3vR3S=Eh{fC4_NFq*Gu#jd&QM=DNW}2Y!^6g?BEUg@I+35HR03$ zuPbIuOX@EE`s;<|@!ZGUHTR+fCnjYcoKq8b@z&){fyZ_wxQZ({vL8ulHhHAd`g74~ zZNB)jLjj%JiXFS9X3hJUQMg#CBjeH=2hFw!#=gR>n`D@-=O%Pz>^n5$=eEsCoTYnI zBnzE77{!a?#0?zHT{5^e<>CZx?pSn2SWe)#z?&^6I1lM8J7HqO>g6@fZ@QMAMxxV1 zx38*EA7)-z#LD&K?fvkWi=2~0T5t85pX4>wa5~|3-qn0=a#MwISg3%T#={nou#AVT z5@{{IF*TK#ixh<;ulh{+fG}sR4n?Z!I$e%DK{s(xRzf{y~Le1m*tc-ztpu` z0sU9gf;jH~U$Q*TpC?Cg2@}7>qchF@Q!n3Oay0nfpm054N^ovq)zzi>?H^s5EOIp% z8YlDXZDkN!S`jcoNO|kW0}7QUDPH1wjh7-^i(iEYvP9@S3Z5^$Hj>MgXT!+}e2Y!C zKl63c-Oy^;n49r(>5Q~hFPF_Ji%RUc%yZ>ohuzeS#Y`5 z25B?ZV!I_cuKn2+U=kl>`Ytp=HJlWqn* zOfJp~RF0?3ve!H|XSu+Ccb$(%M8b1E2J%Q4pLI)|aBK4F0W_hi)-OTmv zq+3j;dNQ;AbWCAwmdMoLe#;m5 z?dBJ?J@WhV&i_rn^Z%8)!9lj?wU-V#|JMy*O>S$~|M%m`^z{!{#I?TIc(wS%3graD zb2}I`bbp1Oe`fRW#!k=Ax1C?Rscm4E6x!T+HMhm1boGhLRmHl@ahVys2b`x>6fNb< zJINgXOX%vdv`N~I%|5%Ojx^3V(!Npie9osu*XMo;S-Cw|C6IY_+(HpnCD+XSdrE7%|9$K;j-|}+q9uAR_2ZA))`E) z8OhRjUbLA@Ka^$XPL(M7AdnovaFkbRfq<}{e(Ph+|NJgJBJ;lq9I{LP7*+Wuc%q*a z#}uvy{3<;R3e#8cwmS(<7fAO!9d#=xiQC|i*$cOS(nF`h^M{@@-svTI!msTR| zGP{viu4M~@yh!(K{-7oPY5_g>be=MCP3*Wa!QD(`(OJcplREBg_#oJ0lBFyj!0BYO zVOiU}M+-FqIlWy>C%10P)Hu&{UDw^~(xh1?PO{EPhrJT{i$j;{{7&vVr?z9EG3Wa1 zw3sKJ?M9c~-+fu`z?&5iJZpw$g0YtB1SYe44}+JMG>9v$4Pg8KM1W0h24jm?W}|S> zMeT)bs?2*VR)rt;y0+=pgcUQGnC)II3|^+QfQ@_81@nU&`*JeeHMt)gvbvKIHa~~K zs+M<60=xH(LsH*1boj1G5C&TN;oRxgnzUHcR1}WpUqj zoY))EA>}wl>;$X)!xx7c9Ct5Td_YTLM)if#&C(0ETL?OSJfJ5im$LeO7z?Yl$FkhQ z(;`Zo>>IfLu$WzcZ0xS~ecumOnKfs;W7mnYy63VQv|jqOJ#wq4#;e*lxt`PiPnjcj z)Z*LO^)2c#Q-$74lAEP_s?L{*t@;eB{J9�hboBU$Ig)Fv{kRvYH)rZrPe$x)IN8 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