From 00d95e1f0f6c7a65ef880286b67ca9e1c865f85c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 1 Mar 2022 02:25:48 -0600 Subject: [PATCH 1/4] Meta: 0.7-pre --- README.org | 4 ++ org-ql.el | 2 +- org-ql.info | 163 ++++++++++++++++++++++++++++------------------------ 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/README.org b/README.org index 1a20b83..8a7f589 100644 --- a/README.org +++ b/README.org @@ -522,6 +522,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.7-pre + +Nothing new yet. + ** 0.6 *Added* diff --git a/org-ql.el b/org-ql.el index 91d2710..ffed560 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.6 +;; Version: 0.7-pre ;; Package-Requires: ((emacs "26.1") (dash "2.18.1") (f "0.17.2") (map "2.1") (org "9.0") (org-super-agenda "1.2") (ov "1.0.6") (peg "1.0") (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 09826ca..1fa166f 100644 --- a/org-ql.info +++ b/org-ql.info @@ -69,6 +69,7 @@ Functions / Macros Changelog +* 0.7-pre: 07-pre. * 0.6: 06. * 0.5.2: 052. * 0.5.1: 051. @@ -957,6 +958,7 @@ releases. * Menu: +* 0.7-pre: 07-pre. * 0.6: 06. * 0.5.2: 052. * 0.5.1: 051. @@ -981,9 +983,17 @@ releases. * 0.1: 01.  -File: README.info, Node: 06, Next: 052, Up: Changelog +File: README.info, Node: 07-pre, Next: 06, Up: Changelog -5.1 0.6 +5.1 0.7-pre +=========== + +Nothing new yet. + + +File: README.info, Node: 06, Next: 052, Prev: 07-pre, Up: Changelog + +5.2 0.6 ======= *Added* @@ -1050,7 +1060,7 @@ File: README.info, Node: 06, Next: 052, Up: Changelog  File: README.info, Node: 052, Next: 051, Prev: 06, Up: Changelog -5.2 0.5.2 +5.3 0.5.2 ========= *Fixed* @@ -1061,7 +1071,7 @@ File: README.info, Node: 052, Next: 051, Prev: 06, Up: Changelog  File: README.info, Node: 051, Next: 05, Prev: 052, Up: Changelog -5.3 0.5.1 +5.4 0.5.1 ========= *Fixed* @@ -1074,7 +1084,7 @@ File: README.info, Node: 051, Next: 05, Prev: 052, Up: Changelog  File: README.info, Node: 05, Next: 049, Prev: 051, Up: Changelog -5.4 0.5 +5.5 0.5 ======= *Added* @@ -1115,7 +1125,7 @@ File: README.info, Node: 05, Next: 049, Prev: 051, Up: Changelog  File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog -5.5 0.4.9 +5.6 0.4.9 ========= *Fixed* @@ -1126,7 +1136,7 @@ File: README.info, Node: 049, Next: 048, Prev: 05, Up: Changelog  File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog -5.6 0.4.8 +5.7 0.4.8 ========= *Fixed* @@ -1138,7 +1148,7 @@ File: README.info, Node: 048, Next: 047, Prev: 049, Up: Changelog  File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog -5.7 0.4.7 +5.8 0.4.7 ========= *Fixed* @@ -1151,7 +1161,7 @@ File: README.info, Node: 047, Next: 046, Prev: 048, Up: Changelog  File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog -5.8 0.4.6 +5.9 0.4.6 ========= *Fixed* @@ -1164,8 +1174,8 @@ File: README.info, Node: 046, Next: 045, Prev: 047, Up: Changelog  File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog -5.9 0.4.5 -========= +5.10 0.4.5 +========== *Fixed* • Non-case-folding predicates like ‘(todo)’ unnecessarily disabled @@ -1176,7 +1186,7 @@ File: README.info, Node: 045, Next: 044, Prev: 046, Up: Changelog  File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog -5.10 0.4.4 +5.11 0.4.4 ========== *Fixed* @@ -1188,7 +1198,7 @@ File: README.info, Node: 044, Next: 043, Prev: 045, Up: Changelog  File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog -5.11 0.4.3 +5.12 0.4.3 ========== *Fixed* @@ -1198,7 +1208,7 @@ File: README.info, Node: 043, Next: 042, Prev: 044, Up: Changelog  File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog -5.12 0.4.2 +5.13 0.4.2 ========== *Fixed* @@ -1207,7 +1217,7 @@ File: README.info, Node: 042, Next: 041, Prev: 043, Up: Changelog  File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog -5.13 0.4.1 +5.14 0.4.1 ========== *Fixed* @@ -1217,7 +1227,7 @@ File: README.info, Node: 041, Next: 04, Prev: 042, Up: Changelog  File: README.info, Node: 04, Next: 032, Prev: 041, Up: Changelog -5.14 0.4 +5.15 0.4 ======== _Note:_ The next release, 0.5, may include changes which will require @@ -1298,7 +1308,7 @@ as they will be pushed to the master branch when ready.  File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog -5.15 0.3.2 +5.16 0.3.2 ========== *Fixed* @@ -1311,7 +1321,7 @@ File: README.info, Node: 032, Next: 031, Prev: 04, Up: Changelog  File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog -5.16 0.3.1 +5.17 0.3.1 ========== *Fixed* @@ -1321,7 +1331,7 @@ File: README.info, Node: 031, Next: 03, Prev: 032, Up: Changelog  File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog -5.17 0.3 +5.18 0.3 ======== *Added* @@ -1386,7 +1396,7 @@ File: README.info, Node: 03, Next: 023, Prev: 031, Up: Changelog  File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog -5.18 0.2.3 +5.19 0.2.3 ========== *Fixed* @@ -1396,7 +1406,7 @@ File: README.info, Node: 023, Next: 022, Prev: 03, Up: Changelog  File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog -5.19 0.2.2 +5.20 0.2.2 ========== *Fixed* @@ -1407,7 +1417,7 @@ File: README.info, Node: 022, Next: 021, Prev: 023, Up: Changelog  File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog -5.20 0.2.1 +5.21 0.2.1 ========== *Fixed* @@ -1417,7 +1427,7 @@ File: README.info, Node: 021, Next: 02, Prev: 022, Up: Changelog  File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog -5.21 0.2 +5.22 0.2 ======== *Added* @@ -1500,7 +1510,7 @@ File: README.info, Node: 02, Next: 01, Prev: 021, Up: Changelog  File: README.info, Node: 01, Prev: 02, Up: Changelog -5.22 0.1 +5.23 0.1 ======== First tagged release. @@ -1558,58 +1568,59 @@ GPLv3  Tag Table: Node: Top225 -Node: Contents1689 -Node: Screenshots1812 -Node: Installation1930 -Node: Quelpa2426 -Node: Helm support2954 -Node: Usage3345 -Node: Commands3743 -Node: org-ql-search4216 -Node: helm-org-ql5866 -Node: org-ql-view6226 -Node: org-ql-view-sidebar6726 -Node: org-ql-view-recent-items7082 -Node: org-ql-sparse-tree7566 -Node: Queries8366 -Node: Non-sexp query syntax9477 -Node: General predicates11201 -Node: Ancestor/descendant predicates17422 -Node: Date/time predicates18550 -Node: Functions / Macros21638 -Node: Agenda-like views21936 -Node: Listing / acting-on results23341 -Node: Custom predicates28977 -Node: Dynamic block32636 -Node: Links35348 -Node: Tips36035 -Node: Changelog36353 -Node: 0637071 -Node: 05240070 -Node: 05140370 -Node: 0540787 -Node: 04942261 -Node: 04842535 -Node: 04742882 -Node: 04643277 -Node: 04543677 -Node: 04444036 -Node: 04344395 -Node: 04244592 -Node: 04144753 -Node: 0444994 -Node: 03248927 -Node: 03149306 -Node: 0349503 -Node: 02352478 -Node: 02252706 -Node: 02152974 -Node: 0253173 -Node: 0157208 -Node: Notes57309 -Node: Comparison with Org Agenda searches57471 -Node: org-sidebar58343 -Node: License58622 +Node: Contents1709 +Node: Screenshots1832 +Node: Installation1950 +Node: Quelpa2446 +Node: Helm support2974 +Node: Usage3365 +Node: Commands3763 +Node: org-ql-search4236 +Node: helm-org-ql5886 +Node: org-ql-view6246 +Node: org-ql-view-sidebar6746 +Node: org-ql-view-recent-items7102 +Node: org-ql-sparse-tree7586 +Node: Queries8386 +Node: Non-sexp query syntax9497 +Node: General predicates11221 +Node: Ancestor/descendant predicates17442 +Node: Date/time predicates18570 +Node: Functions / Macros21658 +Node: Agenda-like views21956 +Node: Listing / acting-on results23361 +Node: Custom predicates28997 +Node: Dynamic block32656 +Node: Links35368 +Node: Tips36055 +Node: Changelog36373 +Node: 07-pre37111 +Node: 0637217 +Node: 05240231 +Node: 05140531 +Node: 0540948 +Node: 04942422 +Node: 04842696 +Node: 04743043 +Node: 04643438 +Node: 04543838 +Node: 04444199 +Node: 04344558 +Node: 04244755 +Node: 04144916 +Node: 0445157 +Node: 03249090 +Node: 03149469 +Node: 0349666 +Node: 02352641 +Node: 02252869 +Node: 02153137 +Node: 0253336 +Node: 0157371 +Node: Notes57472 +Node: Comparison with Org Agenda searches57634 +Node: org-sidebar58506 +Node: License58785  End Tag Table From af18eac2b80b2f56c135f37fcbdcce19fbc34b65 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 1 Mar 2022 02:38:26 -0600 Subject: [PATCH 2/4] Fix: Links to headings with stats cookies in dynamic blocks Fixes #248. Closes #249. Thanks to Maikol Solis (@maikol-solis) for reporting, and to him and Ihor Radchenko (@yantar92) for helping plan the fix. --- README.org | 3 ++- org-ql-search.el | 15 +++++++++--- org-ql.info | 59 ++++++++++++++++++++++++++---------------------- 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/README.org b/README.org index 8a7f589..34c4011 100644 --- a/README.org +++ b/README.org @@ -524,7 +524,8 @@ Simple links may also be written manually in either sexp or non-sexp form, like: ** 0.7-pre -Nothing new yet. +*Fixed* ++ In dynamic blocks, links to headings with statistics cookies were broken. (Fixes [[https://github.com/alphapapa/org-ql/issues/248][#248]]. Thanks to [[https://github.com/maikol-solis][Maikol Solis]] and [[https://github.com/yantar92][Ihor Radchenko]].) ** 0.6 diff --git a/org-ql-search.el b/org-ql-search.el index 4fb5489..aa75656 100644 --- a/org-ql-search.el +++ b/org-ql-search.el @@ -38,6 +38,15 @@ (require 'org-ql) (require 'org-ql-view) +;;;; Compatibility + +(defalias 'org-ql-search--link-heading-search-string + (cond ((fboundp 'org-link--normalize-string) #'org-link--normalize-string) + ((fboundp 'org-link-heading-search-string) #'org-link-heading-search-string) + ((fboundp 'org-make-org-heading-search-string) #'org-make-org-heading-search-string) + (t (warn "org-ql: Unable to define alias `org-ql-search--link-heading-search-string'. This may affect links in dynamic blocks. Please report this as a bug.") + #'identity))) + ;;;; Variables (defvar org-ql-block-header nil @@ -285,9 +294,9 @@ For example, an org-ql dynamic block header could look like: (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-link-display-format - (org-element-property :raw-value element))))) + (let ((normalized-heading + (org-ql-search--link-heading-search-string (org-element-property :raw-value element)))) + (org-make-link-string normalized-heading (org-link-display-format normalized-heading))))) (cons 'priority (lambda (element) (--when-let (org-element-property :priority element) (char-to-string it)))) diff --git a/org-ql.info b/org-ql.info index 1fa166f..a61c3a8 100644 --- a/org-ql.info +++ b/org-ql.info @@ -988,7 +988,12 @@ File: README.info, Node: 07-pre, Next: 06, Up: Changelog 5.1 0.7-pre =========== -Nothing new yet. +*Fixed* + • In dynamic blocks, links to headings with statistics cookies were + broken. (Fixes #248 + (https://github.com/alphapapa/org-ql/issues/248). Thanks to Maikol + Solis (https://github.com/maikol-solis) and Ihor Radchenko + (https://github.com/yantar92).)  File: README.info, Node: 06, Next: 052, Prev: 07-pre, Up: Changelog @@ -1595,32 +1600,32 @@ Node: Links35368 Node: Tips36055 Node: Changelog36373 Node: 07-pre37111 -Node: 0637217 -Node: 05240231 -Node: 05140531 -Node: 0540948 -Node: 04942422 -Node: 04842696 -Node: 04743043 -Node: 04643438 -Node: 04543838 -Node: 04444199 -Node: 04344558 -Node: 04244755 -Node: 04144916 -Node: 0445157 -Node: 03249090 -Node: 03149469 -Node: 0349666 -Node: 02352641 -Node: 02252869 -Node: 02153137 -Node: 0253336 -Node: 0157371 -Node: Notes57472 -Node: Comparison with Org Agenda searches57634 -Node: org-sidebar58506 -Node: License58785 +Node: 0637481 +Node: 05240495 +Node: 05140795 +Node: 0541212 +Node: 04942686 +Node: 04842960 +Node: 04743307 +Node: 04643702 +Node: 04544102 +Node: 04444463 +Node: 04344822 +Node: 04245019 +Node: 04145180 +Node: 0445421 +Node: 03249354 +Node: 03149733 +Node: 0349930 +Node: 02352905 +Node: 02253133 +Node: 02153401 +Node: 0253600 +Node: 0157635 +Node: Notes57736 +Node: Comparison with Org Agenda searches57898 +Node: org-sidebar58770 +Node: License59049  End Tag Table From 73871e04e07abcbb080654a6f19021165c996e0e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 7 Mar 2022 13:49:45 -0600 Subject: [PATCH 3/4] WIP: (logbook) predicate --- org-ql.el | 71 ++++++++++++++++++++++++++++++++++++++++++++ tests/test-org-ql.el | 7 +++++ 2 files changed, 78 insertions(+) diff --git a/org-ql.el b/org-ql.el index ffed560..924f12a 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2134,6 +2134,77 @@ any planning prefix); it defaults to 0 (i.e. the whole regexp)." (from (test-timestamps (ts<= from next-ts))) (to (test-timestamps (ts<= next-ts to))))))) +;;;;;; Logbooks + +(org-ql-defpred logbook (&key string from to on state regexp) + "Return non-nil if current entry has a logbook matching arguments. +FIXME: Document remaining arguments. NOTE: STRING argument is +accepted as first argument rather than only as keyword argument." + ;; TODO: Optionally use (org-log-into-drawer) to detect per-entry + ;; logbook drawers. (It would preclude various optimizations, but + ;; some users might need it.) + :normalizers + ((`(,predicate-names . ,rest) + (let ((string (if (stringp (car rest)) + (prog1 + (regexp-quote (car rest)) + (setf rest (cdr rest))) + (plist-get rest :string))) + (regexp (plist-get rest :regexp)) + (state (plist-get rest :state))) + (org-ql--normalize-from-to-on + `(logbook :string ,string :regexp ,regexp :state ,state + :from ,from :to ,to :on ,on))))) + + ;; TODO: :preambles + + :body + ;; For now, we'll model part of this on `org-log-beginning', though + ;; it may not be fast enough to run on every potential match. + (when-let ((drawer-name (org-log-into-drawer))) + ;; Look for logbook drawer in entry. + (save-excursion + (org-end-of-meta-data) + (let ((drawer-regexp (concat "^[ \t]*:" (regexp-quote drawer-name) ":[ \t]*$")) + (end (if (org-at-heading-p) + (point) + (save-excursion + (outline-next-heading) + (point)))) + (case-fold-search t)) + (when-let ((drawer-element (cl-loop while (re-search-forward drawer-regexp end t) + for element = (org-element-at-point) + when (eq 'drawer (org-element-type element)) + return element))) + ;; Logbook drawer found: narrow to it and confirm that + ;; arguments are found in it. + (save-restriction + (narrow-to-region (point) (org-element-property :contents-end drawer-element)) + (and (or (not string) + (save-excursion + (re-search-forward string nil t))) + (or (not regexp) + (save-excursion + (re-search-forward regexp nil t))) + ;; TODO: from, to, on, state + + ;; TODO: Search notes added like "- Note taken on + ;; [2022-03-07 Mon 13:55] \\" (this starts to get + ;; complicated; org-element might help, but might + ;; also be too slow.. + ))))))) + +(defun org-ql--state-change-regexp (to &optional from) + "Return regexp matching logbook state-change line for states TO and FROM. +Regexp includes an inactive timestamp with hour:minute at +end-of-line." + (let ((from-regexp (if from + `(,(concat "\"" from "\"") (1+ blank)) + ""))) + (rx-to-string `(seq bol (0+ blank) "-" (repeat 1 2 " ") "State " "\"" ,to "\"" (1+ blank) + "from " ,@from-regexp (1+ blank) + (regexp ,org-ql-regexp-ts-inactive-with-time))))) + ;; NOTE: Predicates defined: stop deferring and define normalizer and ;; preamble functions now. Reversing preserves the order in which ;; they were defined. Generally it shouldn't matter, but it might... diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 0b7f2bb..e8cde6a 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -245,6 +245,13 @@ with keyword arg NOW in PLIST." :to-equal '(link :description "DESCRIPTION" :target "TARGET" :regexp-p t)))) + (describe "(logbook)" + (it "with only string argument" + (expect (org-ql--normalize-query '(logbook "String ending in a period.")) + :to-equal '(logbook "String ending in a period\\\.")) + (expect (org-ql--query-string-to-sexp "logbook:called") + :to-equal '(logbook "called")))) + (describe "(outline-path)" (it "with a regexp metacharacter" ;; Ensures that normalizer doesn't infinitely loop. From 870b0c9f5239ef34162d253c8abee84af348969f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 11 Mar 2022 11:07:59 -0600 Subject: [PATCH 4/4] WIP --- org-ql.el | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/org-ql.el b/org-ql.el index 924f12a..83df2a5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2140,9 +2140,6 @@ any planning prefix); it defaults to 0 (i.e. the whole regexp)." "Return non-nil if current entry has a logbook matching arguments. FIXME: Document remaining arguments. NOTE: STRING argument is accepted as first argument rather than only as keyword argument." - ;; TODO: Optionally use (org-log-into-drawer) to detect per-entry - ;; logbook drawers. (It would preclude various optimizations, but - ;; some users might need it.) :normalizers ((`(,predicate-names . ,rest) (let ((string (if (stringp (car rest)) @@ -2156,11 +2153,23 @@ accepted as first argument rather than only as keyword argument." `(logbook :string ,string :regexp ,regexp :state ,state :from ,from :to ,to :on ,on))))) - ;; TODO: :preambles + ;; TODO: :preambles. When arguments are given, search for an + ;; appropriate regexp, then use the :body predicate to confirm it's + ;; in a logbook drawer. Without arguments, simply search for a + ;; logbook drawer (though note that this would preclude using + ;; entry-specific logbook drawer names). :body ;; For now, we'll model part of this on `org-log-beginning', though ;; it may not be fast enough to run on every potential match. + + ;; NOTE: It's regrettable, but since any entry or subtree may define + ;; its own logbook drawer name, to be correct, we must call + ;; `org-log-into-drawer' for each entry. This also means concatting + ;; a regexp string to match such a drawer. + + ;; TODO: Optionally assume default logbook drawer names and optimize + ;; for that case. (when-let ((drawer-name (org-log-into-drawer))) ;; Look for logbook drawer in entry. (save-excursion @@ -2191,7 +2200,10 @@ accepted as first argument rather than only as keyword argument." ;; TODO: Search notes added like "- Note taken on ;; [2022-03-07 Mon 13:55] \\" (this starts to get ;; complicated; org-element might help, but might - ;; also be too slow.. + ;; also be too slow). + + ;; TODO: Without arguments, search for any logbook + ;; entries. ))))))) (defun org-ql--state-change-regexp (to &optional from) @@ -2200,7 +2212,7 @@ Regexp includes an inactive timestamp with hour:minute at end-of-line." (let ((from-regexp (if from `(,(concat "\"" from "\"") (1+ blank)) - ""))) + '("")))) (rx-to-string `(seq bol (0+ blank) "-" (repeat 1 2 " ") "State " "\"" ,to "\"" (1+ blank) "from " ,@from-regexp (1+ blank) (regexp ,org-ql-regexp-ts-inactive-with-time)))))