From fdb80d05c0a1e37d94b8bea1cb4333e2a00176c9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 02:30:58 -0500 Subject: [PATCH 001/970] WIP --- org-agenda-ng.el | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 org-agenda-ng.el diff --git a/org-agenda-ng.el b/org-agenda-ng.el new file mode 100644 index 0000000..7f466fb --- /dev/null +++ b/org-agenda-ng.el @@ -0,0 +1,115 @@ +(require 'org) +(require 'org-agenda) +(require 'dash) +(require 'cl-lib) + +(defun org-agenda-ng--filter-tree (tree &key filter-fns) + (let* ((types '(headline)) + (info nil) + (first-match nil) + (fun (lambda (element) + (when (--all? (cl-typecase it + (function (funcall it element)) + (cons (apply (car it) element (cdr it)))) + filter-fns) + element)))) + (org-element-map tree types fun info first-match))) + + +(defun org-agenda-ng--test () + (let ((tree (cddr (org-element-parse-buffer 'headline))) + (filter-fns '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--scheduled-p < "2017-08-04")))) + (org-agenda-ng--filter-tree tree :filter-fns filter-fns))) + + + +(defun org-agenda-ng--todo-p (element &optional keyword) + "Return non-nil if ELEMENT is a TODO item. +With KEYWORD, return non-nil if it has the same TODO keyword." + (when-let ((element-keyword (org-element-property :todo-keyword element))) + (pcase keyword + ('nil t) + ((pred stringp) + (string= element-keyword keyword)) + (otherwise (error "Invalid keyword argument: %s" otherwise))))) + +(defun org-agenda-ng--scheduled-p (entry &optional comparator target-date) + "Return non-nil if ENTRY is scheduled. +With COMPARATOR and DATE, return non-nil if entry's scheduled +date compares with TARGET-DATE according to COMPARATOR." + + (when-let ((scheduled-date (org-element-property :scheduled entry))) + ;; Append time to target-date because `date-to-day' requires it + (setq target-date (concat target-date " 00:00")) + (setq target-day-number (date-to-day target-date)) + (pcase comparator + ('nil t) + ((and (pred functionp) (guard target-day-number)) + (pcase (org-element-property :type scheduled-date) + ((or 'active 'inactive) + (funcall comparator + (org-time-string-to-absolute + (org-element-timestamp-interpreter scheduled-date 'ignore)) + target-day-number)))) + (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) + +(defun org-agenda-ng--add-scheduled-faces (entry) + "Add faces to ENTRY for its scheduled status." + (if-let ((today-day-number (org-today)) + (scheduled-date (org-element-property :scheduled entry)) + (scheduled-day-number (org-time-string-to-absolute + (org-element-timestamp-interpreter scheduled-date 'ignore))) + (todo-keyword (org-element-property :todo-keyword)) + (done-p (member todo-keyword org-done-keywords)) + (today-p (= today-day-number scheduled-day-number)) + (face (cond + (donep 'org-agenda-done) + (today-p 'org-scheduled-today) + (t 'org-scheduled)))) + (org-add-props entry nil + 'face face) + entry)) + +(defun org-agenda-ng--add-text-properties (element) + "Return ELEMENT as a string with its text-properties set according to its property list. +Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." + (let* ((string (org-element-property :title element)) + (properties (second element)) + (properties (seq-subseq properties 0 24)) ;; FIXME + (properties (cl-loop for (key val) on properties by #'cddr + for key = (intern (cl-subseq (symbol-name key) 1)) + unless (equal key 'raw-value) + + append (list key val)))) + (setq string (org-add-props string properties)) + (setq string (org-agenda-ng--add-scheduled-faces string)) + string)) + +(find-file-noselect "~/org/main.org") +(let ((buffer (find-buffer-visiting "~/org/main.org"))) + (with-current-buffer buffer + (length (org-agenda-ng--test)))) + +(defun argh () + (interactive) + (with-current-buffer (find-buffer-visiting "~/org/main.org") + (let* ((entries (cl-subseq (org-agenda-ng--test) 0 2)) + (result-string (org-agenda-finalize-entries (mapcar #'org-agenda-ng--add-text-properties + entries) + 'agenda)) + (target-buffer (get-buffer-create "test-agenda-ng"))) + (with-current-buffer target-buffer + (read-only-mode -1) + (erase-buffer) + (insert result-string) + (read-only-mode 1) + (pop-to-buffer (current-buffer)))))) + +;; (with-current-buffer (find-file "~/src/org-agenda-ng/org-agenda-ng.el") +;; (eval-buffer)) + +;; (decode-time (days-to-time 730119)) +;; (date-to-day "2017-08-04") + +;; (date-to-day "2017-08-03") From 6d18c1bee586c9c86bb354fa9fcc699b5cf66a0d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 02:39:24 -0500 Subject: [PATCH 002/970] Progress --- org-agenda-ng.el | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 7f466fb..0c8edd7 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -56,30 +56,34 @@ date compares with TARGET-DATE according to COMPARATOR." (defun org-agenda-ng--add-scheduled-faces (entry) "Add faces to ENTRY for its scheduled status." - (if-let ((today-day-number (org-today)) - (scheduled-date (org-element-property :scheduled entry)) - (scheduled-day-number (org-time-string-to-absolute - (org-element-timestamp-interpreter scheduled-date 'ignore))) - (todo-keyword (org-element-property :todo-keyword)) - (done-p (member todo-keyword org-done-keywords)) - (today-p (= today-day-number scheduled-day-number)) - (face (cond - (donep 'org-agenda-done) - (today-p 'org-scheduled-today) - (t 'org-scheduled)))) - (org-add-props entry nil - 'face face) + (if-let ((scheduled-date (org-find-text-property-in-string 'scheduled entry))) + (let* ((today-day-number (org-today)) + (scheduled-day-number (org-time-string-to-absolute + (org-element-timestamp-interpreter scheduled-date 'ignore))) + (todo-keyword (org-find-text-property-in-string 'todo-keyword entry)) + (done-p (member todo-keyword org-done-keywords)) + (today-p (= today-day-number scheduled-day-number)) + (face (cond + (done-p 'org-agenda-done) + (today-p 'org-scheduled-today) + (t 'org-scheduled)))) + (org-add-props entry nil + 'face face)) + ;; Not scheduled entry)) + + (defun org-agenda-ng--add-text-properties (element) "Return ELEMENT as a string with its text-properties set according to its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." (let* ((string (org-element-property :title element)) (properties (second element)) - (properties (seq-subseq properties 0 24)) ;; FIXME + ;(properties (seq-subseq properties 0 (1- (length properties)))) ;; FIXME + ; (properties (cl-subseq properties (- (length properties) 2))) (properties (cl-loop for (key val) on properties by #'cddr for key = (intern (cl-subseq (symbol-name key) 1)) - unless (equal key 'raw-value) + unless (member key '(raw-value parent)) ; FIXME: Is this the right way to do this, or really necessary? append (list key val)))) (setq string (org-add-props string properties)) From 46f6921af170029099c67a70ab2f682b15c76740 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 03:28:44 -0500 Subject: [PATCH 003/970] More progress --- org-agenda-ng.el | 70 +++++++++++++++++++++++++++++++----------------- 1 file changed, 46 insertions(+), 24 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 0c8edd7..abc4b3f 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -54,51 +54,73 @@ date compares with TARGET-DATE according to COMPARATOR." target-day-number)))) (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) -(defun org-agenda-ng--add-scheduled-faces (entry) - "Add faces to ENTRY for its scheduled status." - (if-let ((scheduled-date (org-find-text-property-in-string 'scheduled entry))) +(defun org-agenda-ng--add-faces (element) + (org-agenda-ng--add-scheduled-faces element)) + +(defun org-agenda-ng--add-scheduled-faces (element) + "Add faces to ELEMENT's title for its scheduled status." + (if-let ((scheduled-date (org-element-property :scheduled element))) (let* ((today-day-number (org-today)) (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) - (todo-keyword (org-find-text-property-in-string 'todo-keyword entry)) + (todo-keyword (org-element-property :todo-keyword element)) (done-p (member todo-keyword org-done-keywords)) (today-p (= today-day-number scheduled-day-number)) (face (cond (done-p 'org-agenda-done) (today-p 'org-scheduled-today) - (t 'org-scheduled)))) - (org-add-props entry nil - 'face face)) + (t 'org-scheduled))) + (title (--> (org-element-property :title element) + (org-add-props it nil + 'face face))) + (properties (--> (second element) + (plist-put it :title title)))) + (list (car element) + properties)) ;; Not scheduled - entry)) - - + element)) (defun org-agenda-ng--add-text-properties (element) "Return ELEMENT as a string with its text-properties set according to its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." - (let* ((string (org-element-property :title element)) - (properties (second element)) - ;(properties (seq-subseq properties 0 (1- (length properties)))) ;; FIXME - ; (properties (cl-subseq properties (- (length properties) 2))) + (let* ((properties (second element)) + ;; Remove the :parent property, which so bloats the size of + ;; the properties list that it makes it essentially + ;; impossible to debug, because Emacs takes approximately + ;; forever to show it in the minibuffer or with + ;; `describe-text-properties'. Also, remove ":" from key + ;; symbols. (properties (cl-loop for (key val) on properties by #'cddr for key = (intern (cl-subseq (symbol-name key) 1)) - unless (member key '(raw-value parent)) ; FIXME: Is this the right way to do this, or really necessary? + unless (member key '(parent)) + append (list key val))) + (title (--> (org-agenda-ng--add-faces element) + (org-element-property :title it) + (org-link-display-format it) + ;; Add element properties to the title so --add-faces can find them. + ;; MAYBE: Rewrite --add-faces/etc. to take a props argument. + (org-add-props it properties) + )) + (todo-keyword (--> (org-element-property :todo-keyword element) + (org-agenda-ng--add-todo-face it))) + (string (s-join " " (list todo-keyword title)))) + ;; Add all the necessary properties and faces to the whole string + (--> string + (org-add-props it properties)))) - append (list key val)))) - (setq string (org-add-props string properties)) - (setq string (org-agenda-ng--add-scheduled-faces string)) - string)) +(defun org-agenda-ng--add-todo-face (keyword) + (when-let ((face (org-get-todo-face keyword))) + (org-add-props keyword nil 'face face))) -(find-file-noselect "~/org/main.org") -(let ((buffer (find-buffer-visiting "~/org/main.org"))) - (with-current-buffer buffer - (length (org-agenda-ng--test)))) +;; (find-file-noselect "~/org/main.org") +;; (let ((buffer (find-buffer-visiting "~/org/main.org"))) +;; (with-current-buffer buffer +;; (length (org-agenda-ng--test)))) (defun argh () (interactive) (with-current-buffer (find-buffer-visiting "~/org/main.org") - (let* ((entries (cl-subseq (org-agenda-ng--test) 0 2)) + (let* ((entries (org-agenda-ng--test)) (result-string (org-agenda-finalize-entries (mapcar #'org-agenda-ng--add-text-properties entries) 'agenda)) From a40b00532d3a8d60a4a2aff4f105f706521738f9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 03:33:47 -0500 Subject: [PATCH 004/970] More --- org-agenda-ng.el | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index abc4b3f..887f75f 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -3,6 +3,23 @@ (require 'dash) (require 'cl-lib) +(defun org-agenda-ng--test-agenda () + (interactive) + (with-current-buffer (find-buffer-visiting "~/org/main.org") + (let* ((tree (cddr (org-element-parse-buffer 'headline))) + (filter-fns '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--scheduled-p < "2017-08-04"))) + (entries (--> (org-agenda-ng--filter-tree tree :filter-fns filter-fns) + (mapcar #'org-agenda-ng--add-text-properties it))) + (result-string (org-agenda-finalize-entries entries 'agenda)) + (target-buffer (get-buffer-create "test-agenda-ng"))) + (with-current-buffer target-buffer + (read-only-mode -1) + (erase-buffer) + (insert result-string) + (read-only-mode 1) + (pop-to-buffer (current-buffer)))))) + (defun org-agenda-ng--filter-tree (tree &key filter-fns) (let* ((types '(headline)) (info nil) @@ -15,15 +32,6 @@ element)))) (org-element-map tree types fun info first-match))) - -(defun org-agenda-ng--test () - (let ((tree (cddr (org-element-parse-buffer 'headline))) - (filter-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--scheduled-p < "2017-08-04")))) - (org-agenda-ng--filter-tree tree :filter-fns filter-fns))) - - - (defun org-agenda-ng--todo-p (element &optional keyword) "Return non-nil if ELEMENT is a TODO item. With KEYWORD, return non-nil if it has the same TODO keyword." @@ -96,11 +104,7 @@ Its property list should be the second item in the list, as returned by `org-ele append (list key val))) (title (--> (org-agenda-ng--add-faces element) (org-element-property :title it) - (org-link-display-format it) - ;; Add element properties to the title so --add-faces can find them. - ;; MAYBE: Rewrite --add-faces/etc. to take a props argument. - (org-add-props it properties) - )) + (org-link-display-format it))) (todo-keyword (--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) (string (s-join " " (list todo-keyword title)))) @@ -117,20 +121,7 @@ Its property list should be the second item in the list, as returned by `org-ele ;; (with-current-buffer buffer ;; (length (org-agenda-ng--test)))) -(defun argh () - (interactive) - (with-current-buffer (find-buffer-visiting "~/org/main.org") - (let* ((entries (org-agenda-ng--test)) - (result-string (org-agenda-finalize-entries (mapcar #'org-agenda-ng--add-text-properties - entries) - 'agenda)) - (target-buffer (get-buffer-create "test-agenda-ng"))) - (with-current-buffer target-buffer - (read-only-mode -1) - (erase-buffer) - (insert result-string) - (read-only-mode 1) - (pop-to-buffer (current-buffer)))))) + ;; (with-current-buffer (find-file "~/src/org-agenda-ng/org-agenda-ng.el") ;; (eval-buffer)) From 9dfb9b98c06c8f00e8812b31d6af873ad78435ea Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 03:42:15 -0500 Subject: [PATCH 005/970] This is starting to show potential But the Org agenda codebase is massive, and reimplementing all of it is crazy --- org-agenda-ng.el | 125 ++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 66 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 887f75f..63526ca 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -3,14 +3,16 @@ (require 'dash) (require 'cl-lib) +;;;; Commands + (defun org-agenda-ng--test-agenda () (interactive) (with-current-buffer (find-buffer-visiting "~/org/main.org") (let* ((tree (cddr (org-element-parse-buffer 'headline))) (filter-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--scheduled-p < "2017-08-04"))) + (org-agenda-ng--date-p :deadline < "2017-08-05"))) (entries (--> (org-agenda-ng--filter-tree tree :filter-fns filter-fns) - (mapcar #'org-agenda-ng--add-text-properties it))) + (mapcar #'org-agenda-ng--element-to-string it))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer @@ -20,6 +22,8 @@ (read-only-mode 1) (pop-to-buffer (current-buffer)))))) +;;;; Functions + (defun org-agenda-ng--filter-tree (tree &key filter-fns) (let* ((types '(headline)) (info nil) @@ -32,35 +36,31 @@ element)))) (org-element-map tree types fun info first-match))) -(defun org-agenda-ng--todo-p (element &optional keyword) - "Return non-nil if ELEMENT is a TODO item. -With KEYWORD, return non-nil if it has the same TODO keyword." - (when-let ((element-keyword (org-element-property :todo-keyword element))) - (pcase keyword - ('nil t) - ((pred stringp) - (string= element-keyword keyword)) - (otherwise (error "Invalid keyword argument: %s" otherwise))))) +;;;; Faces/properties -(defun org-agenda-ng--scheduled-p (entry &optional comparator target-date) - "Return non-nil if ENTRY is scheduled. -With COMPARATOR and DATE, return non-nil if entry's scheduled -date compares with TARGET-DATE according to COMPARATOR." - - (when-let ((scheduled-date (org-element-property :scheduled entry))) - ;; Append time to target-date because `date-to-day' requires it - (setq target-date (concat target-date " 00:00")) - (setq target-day-number (date-to-day target-date)) - (pcase comparator - ('nil t) - ((and (pred functionp) (guard target-day-number)) - (pcase (org-element-property :type scheduled-date) - ((or 'active 'inactive) - (funcall comparator - (org-time-string-to-absolute - (org-element-timestamp-interpreter scheduled-date 'ignore)) - target-day-number)))) - (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) +(defun org-agenda-ng--element-to-string (element) + "Return ELEMENT as a string with its text-properties set according to its property list. +Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." + (let* ((properties (second element)) + ;; Remove the :parent property, which so bloats the size of + ;; the properties list that it makes it essentially + ;; impossible to debug, because Emacs takes approximately + ;; forever to show it in the minibuffer or with + ;; `describe-text-properties'. Also, remove ":" from key + ;; symbols. + (properties (cl-loop for (key val) on properties by #'cddr + for key = (intern (cl-subseq (symbol-name key) 1)) + unless (member key '(parent)) + append (list key val))) + (title (--> (org-agenda-ng--add-faces element) + (org-element-property :title it) + (org-link-display-format it))) + (todo-keyword (--> (org-element-property :todo-keyword element) + (org-agenda-ng--add-todo-face it))) + (string (s-join " " (list todo-keyword title)))) + ;; Add all the necessary properties and faces to the whole string + (--> string + (org-add-props it properties)))) (defun org-agenda-ng--add-faces (element) (org-agenda-ng--add-scheduled-faces element)) @@ -88,45 +88,38 @@ date compares with TARGET-DATE according to COMPARATOR." ;; Not scheduled element)) -(defun org-agenda-ng--add-text-properties (element) - "Return ELEMENT as a string with its text-properties set according to its property list. -Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." - (let* ((properties (second element)) - ;; Remove the :parent property, which so bloats the size of - ;; the properties list that it makes it essentially - ;; impossible to debug, because Emacs takes approximately - ;; forever to show it in the minibuffer or with - ;; `describe-text-properties'. Also, remove ":" from key - ;; symbols. - (properties (cl-loop for (key val) on properties by #'cddr - for key = (intern (cl-subseq (symbol-name key) 1)) - unless (member key '(parent)) - append (list key val))) - (title (--> (org-agenda-ng--add-faces element) - (org-element-property :title it) - (org-link-display-format it))) - (todo-keyword (--> (org-element-property :todo-keyword element) - (org-agenda-ng--add-todo-face it))) - (string (s-join " " (list todo-keyword title)))) - ;; Add all the necessary properties and faces to the whole string - (--> string - (org-add-props it properties)))) - (defun org-agenda-ng--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) -;; (find-file-noselect "~/org/main.org") -;; (let ((buffer (find-buffer-visiting "~/org/main.org"))) -;; (with-current-buffer buffer -;; (length (org-agenda-ng--test)))) +;;;; Predicates +(defun org-agenda-ng--todo-p (element &optional keyword) + "Return non-nil if ELEMENT is a TODO item. +With KEYWORD, return non-nil if it has the same TODO keyword." + (when-let ((element-keyword (org-element-property :todo-keyword element))) + (pcase keyword + ('nil t) + ((pred stringp) + (string= element-keyword keyword)) + (otherwise (error "Invalid keyword argument: %s" otherwise))))) - -;; (with-current-buffer (find-file "~/src/org-agenda-ng/org-agenda-ng.el") -;; (eval-buffer)) - -;; (decode-time (days-to-time 730119)) -;; (date-to-day "2017-08-04") - -;; (date-to-day "2017-08-03") +(defun org-agenda-ng--date-p (entry type &optional comparator target-date) + "Return non-nil if ENTRY has a date property of TYPE. +TYPE should be a keyword symbol, like :scheduled or :deadline. +With COMPARATOR and DATE, return non-nil if entry's scheduled +date compares with TARGET-DATE according to COMPARATOR." + (when-let ((entry-date (org-element-property type entry))) + ;; Append time to target-date because `date-to-day' requires it + (setq target-date (concat target-date " 00:00")) + (setq target-day-number (date-to-day target-date)) + (pcase comparator + ('nil t) + ((and (pred functionp) (guard target-day-number)) + (pcase (org-element-property :type entry-date) + ((or 'active 'inactive) + (funcall comparator + (org-time-string-to-absolute + (org-element-timestamp-interpreter entry-date 'ignore)) + target-day-number)))) + (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) From 42023152837c9857ff5efc97f2111e739191486a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 03:49:38 -0500 Subject: [PATCH 006/970] Hmm --- org-agenda-ng.el | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 63526ca..1826828 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -5,12 +5,9 @@ ;;;; Commands -(defun org-agenda-ng--test-agenda () - (interactive) +(defun org-agenda-ng--agenda (&key filter-fns) (with-current-buffer (find-buffer-visiting "~/org/main.org") (let* ((tree (cddr (org-element-parse-buffer 'headline))) - (filter-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--date-p :deadline < "2017-08-05"))) (entries (--> (org-agenda-ng--filter-tree tree :filter-fns filter-fns) (mapcar #'org-agenda-ng--element-to-string it))) (result-string (org-agenda-finalize-entries entries 'agenda)) @@ -22,6 +19,17 @@ (read-only-mode 1) (pop-to-buffer (current-buffer)))))) +(defun org-agenda-ng--test-agenda () + (interactive) + (org-agenda-ng--agenda + :filter-fns '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--date-p :deadline < "2017-08-05")))) + +(defun org-agenda-ng--todo-list () + (interactive) + (org-agenda-ng--agenda + :filter-fns '((org-agenda-ng--todo-p "TODO")))) + ;;;; Functions (defun org-agenda-ng--filter-tree (tree &key filter-fns) @@ -57,7 +65,11 @@ Its property list should be the second item in the list, as returned by `org-ele (org-link-display-format it))) (todo-keyword (--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) - (string (s-join " " (list todo-keyword title)))) + (tags (--> (org-element-property :tags element) + (s-join ":" it) + (s-wrap it ":") + (org-add-props it nil 'face 'org-tag))) + (string (s-join " " (list todo-keyword title tags)))) ;; Add all the necessary properties and faces to the whole string (--> string (org-add-props it properties)))) From 4f81c672ff3d86e742b683ab5952371adb1a37c1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 04:18:12 -0500 Subject: [PATCH 007/970] More --- org-agenda-ng.el | 50 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 1826828..c2d0a07 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -1,3 +1,17 @@ +;;; Commentary: + +;;;; Principles + +;;;;; Work on elements + +;; We want to work on elements as returned by =org-element-parse-buffer=. We only convert to strings at the very end, when we send the list of those to =org-agenda-finalize-entries=. + +;;;;; Preserve the call to =org-agenda-finalize-entries= + +;; We want to preserve the final call to =org-agenda-finalize-entries= to preserve compatibility with other packages and functions. + +;;; Code: + (require 'org) (require 'org-agenda) (require 'dash) @@ -5,11 +19,11 @@ ;;;; Commands -(defun org-agenda-ng--agenda (&key filter-fns) +(cl-defun org-agenda-ng--agenda (&key match-fns) (with-current-buffer (find-buffer-visiting "~/org/main.org") (let* ((tree (cddr (org-element-parse-buffer 'headline))) - (entries (--> (org-agenda-ng--filter-tree tree :filter-fns filter-fns) - (mapcar #'org-agenda-ng--element-to-string it))) + (entries (--> (org-agenda-ng--filter-tree tree :match-fns match-fns) + (mapcar #'org-agenda-ng--format-element it))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer @@ -22,17 +36,17 @@ (defun org-agenda-ng--test-agenda () (interactive) (org-agenda-ng--agenda - :filter-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--date-p :deadline < "2017-08-05")))) + :match-fns '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--date-p :deadline < "2017-08-05")))) (defun org-agenda-ng--todo-list () (interactive) (org-agenda-ng--agenda - :filter-fns '((org-agenda-ng--todo-p "TODO")))) + :match-fns '((org-agenda-ng--todo-p "TODO")))) ;;;; Functions -(defun org-agenda-ng--filter-tree (tree &key filter-fns) +(defun org-agenda-ng--filter-tree (tree &key match-fns) (let* ((types '(headline)) (info nil) (first-match nil) @@ -40,13 +54,16 @@ (when (--all? (cl-typecase it (function (funcall it element)) (cons (apply (car it) element (cdr it)))) - filter-fns) + match-fns) element)))) (org-element-map tree types fun info first-match))) + ;;;; Faces/properties -(defun org-agenda-ng--element-to-string (element) +(defun org-agenda-ng--format-element (element) + ;; This essentially needs to do what `org-agenda-format-item' does, + ;; which is a lot. "Return ELEMENT as a string with its text-properties set according to its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." (let* ((properties (second element)) @@ -63,13 +80,16 @@ Its property list should be the second item in the list, as returned by `org-ele (title (--> (org-agenda-ng--add-faces element) (org-element-property :title it) (org-link-display-format it))) - (todo-keyword (--> (org-element-property :todo-keyword element) - (org-agenda-ng--add-todo-face it))) - (tags (--> (org-element-property :tags element) - (s-join ":" it) - (s-wrap it ":") - (org-add-props it nil 'face 'org-tag))) + (todo-keyword (-some--> (org-element-property :todo-keyword element) + (org-agenda-ng--add-todo-face it))) + (tags (-some--> (org-element-property :tags element) + (s-join ":" it) + (s-wrap it ":") + (org-add-props it nil 'face 'org-tag))) + (level (org-element-property :level element)) + (category (org-element-property :category element)) (string (s-join " " (list todo-keyword title tags)))) + (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string (org-add-props it properties)))) From 3b871552bdb72cdd92d48442745ca0a6b7bfc987 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 04:48:06 -0500 Subject: [PATCH 008/970] More --- org-agenda-ng.el | 103 ++++++++++++++++++++++++++++++----------------- 1 file changed, 65 insertions(+), 38 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c2d0a07..1558e35 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -19,42 +19,59 @@ ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key match-fns) - (with-current-buffer (find-buffer-visiting "~/org/main.org") - (let* ((tree (cddr (org-element-parse-buffer 'headline))) - (entries (--> (org-agenda-ng--filter-tree tree :match-fns match-fns) - (mapcar #'org-agenda-ng--format-element it))) - (result-string (org-agenda-finalize-entries entries 'agenda)) - (target-buffer (get-buffer-create "test-agenda-ng"))) - (with-current-buffer target-buffer - (read-only-mode -1) - (erase-buffer) - (insert result-string) - (read-only-mode 1) - (pop-to-buffer (current-buffer)))))) +(cl-defun org-agenda-ng--agenda (&key match-fns filter-fns) + (let* ((tree (cddr (org-element-parse-buffer 'headline))) + (entries (--> (org-agenda-ng--filter-tree tree :match-fns match-fns :filter-fns filter-fns) + (mapcar #'org-agenda-ng--format-element it))) + (result-string (org-agenda-finalize-entries entries 'agenda)) + (target-buffer (get-buffer-create "test-agenda-ng"))) + (with-current-buffer target-buffer + (read-only-mode -1) + (erase-buffer) + (insert result-string) + (read-only-mode 1) + (pop-to-buffer (current-buffer))))) + +(defmacro org-agenda-ng--test (&rest args) + `(with-current-buffer (find-buffer-visiting "~/org/main.org") + (org-agenda-ng--agenda + ,@args))) (defun org-agenda-ng--test-agenda () (interactive) - (org-agenda-ng--agenda + (org-agenda-ng--test :match-fns '((org-agenda-ng--todo-p "TODO") (org-agenda-ng--date-p :deadline < "2017-08-05")))) -(defun org-agenda-ng--todo-list () +(defun org-agenda-ng--test-agenda-today () (interactive) - (org-agenda-ng--agenda - :match-fns '((org-agenda-ng--todo-p "TODO")))) + (org-agenda-ng--test + :match-fns `((org-agenda-ng--date-p :deadline <= ,(org-today)) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :filter-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) + +(defun org-agenda-ng--test-todo-list () + (interactive) + (org-agenda-ng--test + :match-fns '(org-agenda-ng--todo-p) + :filter-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) ;;;; Functions -(defun org-agenda-ng--filter-tree (tree &key match-fns) +(cl-defun org-agenda-ng--filter-tree (tree &key match-fns filter-fns) (let* ((types '(headline)) (info nil) (first-match nil) (fun (lambda (element) - (when (--all? (cl-typecase it - (function (funcall it element)) - (cons (apply (car it) element (cdr it)))) - match-fns) + (when (and (--any? (cl-typecase it + (function (funcall it element)) + (cons (apply (car it) element (cdr it)))) + match-fns) + (or (null filter-fns) + (--none? (cl-typecase it + (function (funcall it element)) + (cons (apply (car it) element (cdr it)))) + filter-fns))) element)))) (org-element-map tree types fun info first-match))) @@ -126,32 +143,42 @@ Its property list should be the second item in the list, as returned by `org-ele ;;;; Predicates -(defun org-agenda-ng--todo-p (element &optional keyword) +(defun org-agenda-ng--todo-p (element &optional keywords) "Return non-nil if ELEMENT is a TODO item. -With KEYWORD, return non-nil if it has the same TODO keyword." +With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (when-let ((element-keyword (org-element-property :todo-keyword element))) - (pcase keyword + (pcase keywords ('nil t) ((pred stringp) - (string= element-keyword keyword)) + (string= element-keyword keywords)) + ((pred listp) + (member element-keyword keywords)) (otherwise (error "Invalid keyword argument: %s" otherwise))))) (defun org-agenda-ng--date-p (entry type &optional comparator target-date) "Return non-nil if ENTRY has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. -With COMPARATOR and DATE, return non-nil if entry's scheduled -date compares with TARGET-DATE according to COMPARATOR." + +With COMPARATOR and TARGET-DATE, return non-nil if entry's +scheduled date compares with TARGET-DATE according to COMPARATOR. +TARGET-DATE may be a string like \"2017-08-05\", or an integer +like one returned by `date-to-day'." (when-let ((entry-date (org-element-property type entry))) - ;; Append time to target-date because `date-to-day' requires it - (setq target-date (concat target-date " 00:00")) - (setq target-day-number (date-to-day target-date)) (pcase comparator + ;; Not comparing, just checking if it has one ('nil t) - ((and (pred functionp) (guard target-day-number)) - (pcase (org-element-property :type entry-date) - ((or 'active 'inactive) - (funcall comparator - (org-time-string-to-absolute - (org-element-timestamp-interpreter entry-date 'ignore)) - target-day-number)))) + ;; Compare dates + ((and (pred functionp) (guard target-date)) + (let ((target-day-number (cl-typecase target-date + ;; Append time to target-date + ;; because `date-to-day' requires it + (string (date-to-day (concat target-date " 00:00"))) + (integer target-date)))) + (pcase (org-element-property :type entry-date) + ((or 'active 'inactive) + (funcall comparator + (org-time-string-to-absolute + (org-element-timestamp-interpreter entry-date 'ignore)) + target-day-number)) + (error "Unknown entry-date type: %s" (org-element-property :type entry-date))))) (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) From 1a42de9293f23a138ffecd633d870b87d2f55425 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 05:18:55 -0500 Subject: [PATCH 009/970] Add markers and stuff --- org-agenda-ng.el | 67 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 1558e35..3352fc8 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -20,7 +20,8 @@ ;;;; Commands (cl-defun org-agenda-ng--agenda (&key match-fns filter-fns) - (let* ((tree (cddr (org-element-parse-buffer 'headline))) + (let* ((org-use-tag-inheritance t) + (tree (cddr (org-element-parse-buffer 'headline))) (entries (--> (org-agenda-ng--filter-tree tree :match-fns match-fns :filter-fns filter-fns) (mapcar #'org-agenda-ng--format-element it))) (result-string (org-agenda-finalize-entries entries 'agenda)) @@ -46,7 +47,8 @@ (defun org-agenda-ng--test-agenda-today () (interactive) (org-agenda-ng--test - :match-fns `((org-agenda-ng--date-p :deadline <= ,(org-today)) + :match-fns `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) (org-agenda-ng--date-p :scheduled <= ,(org-today))) :filter-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) @@ -72,6 +74,13 @@ (function (funcall it element)) (cons (apply (car it) element (cdr it)))) filter-fns))) + ;; Add marker to element properties + ;; TODO: Probably want to use a list of transforming functions here + (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) + (properties (second element)) + (properties (plist-put properties :org-hd-marker marker))) + (setf (second element) properties)) + ;; Return element element)))) (org-element-map tree types fun info first-match))) @@ -99,22 +108,34 @@ Its property list should be the second item in the list, as returned by `org-ele (org-link-display-format it))) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) - (tags (-some--> (org-element-property :tags element) - (s-join ":" it) - (s-wrap it ":") - (org-add-props it nil 'face 'org-tag))) + (tag-list (if org-agenda-use-tag-inheritance + (if-let ((marker (or (org-element-property :org-hd-marker element) + (org-element-property :org-marker element)))) + (org-with-point-at marker + (message "Getting tags for: %s" title) + (org-get-tags-at)) + ;; No marker found + (warn "No marker found for item: %s" title) + (org-element-property :tags element)) + (org-element-property :tags element))) + (tag-string (-some--> tag-list + (s-join ":" it) + (s-wrap it ":") + (org-add-props it nil 'face 'org-tag))) (level (org-element-property :level element)) (category (org-element-property :category element)) - (string (s-join " " (list todo-keyword title tags)))) + (string (s-join " " (list todo-keyword title tag-string)))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string - (org-add-props it properties)))) + (org-add-props it properties 'tags tag-list)))) (defun org-agenda-ng--add-faces (element) - (org-agenda-ng--add-scheduled-faces element)) + (->> element + (org-agenda-ng--add-scheduled-face) + (org-agenda-ng--add-deadline-face))) -(defun org-agenda-ng--add-scheduled-faces (element) +(defun org-agenda-ng--add-scheduled-face (element) "Add faces to ELEMENT's title for its scheduled status." (if-let ((scheduled-date (org-element-property :scheduled element))) (let* ((today-day-number (org-today)) @@ -137,6 +158,32 @@ Its property list should be the second item in the list, as returned by `org-ele ;; Not scheduled element)) +(defun org-agenda-ng--add-deadline-face (element) + "Add faces to ELEMENT's title for its deadline status." + (if-let ((deadline-date (org-element-property :deadline element))) + (let* ((today-day-number (org-today)) + (deadline-day-number (org-time-string-to-absolute + (org-element-timestamp-interpreter deadline-date 'ignore))) + (todo-keyword (org-element-property :todo-keyword element)) + (done-p (member todo-keyword org-done-keywords)) + (today-p (= today-day-number deadline-day-number)) + (deadline-passed-fraction (--> (- deadline-day-number today-day-number) + (float it) + (/ it (max org-deadline-warning-days 1)) + (- 1 it))) + (face (org-agenda-deadline-face deadline-passed-fraction)) + (title (--> (org-element-property :title element) + (org-add-props it nil + 'face face))) + (properties (--> (second element) + (plist-put it :title title)))) + (list (car element) + properties)) + ;; No deadline + element)) + + + (defun org-agenda-ng--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) From 99f7456213ac02cf5a12b7576b22cf516262228b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 05:36:54 -0500 Subject: [PATCH 010/970] Add priority face --- org-agenda-ng.el | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 3352fc8..7d34310 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -124,7 +124,11 @@ Its property list should be the second item in the list, as returned by `org-ele (org-add-props it nil 'face 'org-tag))) (level (org-element-property :level element)) (category (org-element-property :category element)) - (string (s-join " " (list todo-keyword title tag-string)))) + (priority-string (-some->> (org-element-property :priority element) + (char-to-string) + (format "[#%s]") + (org-agenda-ng--add-priority-face))) + (string (s-join " " (list todo-keyword priority-string title tag-string)))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string @@ -135,6 +139,12 @@ Its property list should be the second item in the list, as returned by `org-ele (org-agenda-ng--add-scheduled-face) (org-agenda-ng--add-deadline-face))) +(defun org-agenda-ng--add-priority-face (string) + "Return STRING with priority face added." + (when (string-match "\\(\\[#\\(.\\)\\]\\)" string) + (let ((face (org-get-priority-face (string-to-char (match-string 2))))) + (org-add-props string nil 'face face 'font-lock-fontified t)))) + (defun org-agenda-ng--add-scheduled-face (element) "Add faces to ELEMENT's title for its scheduled status." (if-let ((scheduled-date (org-element-property :scheduled element))) From cec536b793400156f0d89b491348194aa7079ac3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 05:37:33 -0500 Subject: [PATCH 011/970] More --- org-agenda-ng.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 7d34310..553935c 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -89,7 +89,7 @@ (defun org-agenda-ng--format-element (element) ;; This essentially needs to do what `org-agenda-format-item' does, - ;; which is a lot. + ;; which is a lot. We are a long way from that, but it's a start. "Return ELEMENT as a string with its text-properties set according to its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." (let* ((properties (second element)) From aa722987b0bf772b0185a02570c74fa99935965c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 05:42:06 -0500 Subject: [PATCH 012/970] More --- org-agenda-ng.el | 51 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 553935c..4d5151e 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -19,10 +19,10 @@ ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key match-fns filter-fns) +(cl-defun org-agenda-ng--agenda (&key any-fns none-fns) (let* ((org-use-tag-inheritance t) (tree (cddr (org-element-parse-buffer 'headline))) - (entries (--> (org-agenda-ng--filter-tree tree :match-fns match-fns :filter-fns filter-fns) + (entries (--> (org-agenda-ng--filter-tree tree :any-fns any-fns :none-fns none-fns) (mapcar #'org-agenda-ng--format-element it))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) @@ -41,26 +41,26 @@ (defun org-agenda-ng--test-agenda () (interactive) (org-agenda-ng--test - :match-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--date-p :deadline < "2017-08-05")))) + :any-fns '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--date-p :deadline < "2017-08-05")))) (defun org-agenda-ng--test-agenda-today () (interactive) (org-agenda-ng--test - :match-fns `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :filter-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) + :any-fns `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) (defun org-agenda-ng--test-todo-list () (interactive) (org-agenda-ng--test - :match-fns '(org-agenda-ng--todo-p) - :filter-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) + :any-fns '(org-agenda-ng--todo-p) + :none-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) ;;;; Functions -(cl-defun org-agenda-ng--filter-tree (tree &key match-fns filter-fns) +(cl-defun org-agenda-ng--filter-tree (tree &key any-fns none-fns) (let* ((types '(headline)) (info nil) (first-match nil) @@ -68,25 +68,29 @@ (when (and (--any? (cl-typecase it (function (funcall it element)) (cons (apply (car it) element (cdr it)))) - match-fns) - (or (null filter-fns) + any-fns) + ;; Don't return if any filters match + (or (null none-fns) (--none? (cl-typecase it (function (funcall it element)) (cons (apply (car it) element (cdr it)))) - filter-fns))) - ;; Add marker to element properties - ;; TODO: Probably want to use a list of transforming functions here - (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) - (properties (second element)) - (properties (plist-put properties :org-hd-marker marker))) - (setf (second element) properties)) + none-fns))) ;; Return element - element)))) + (->> element + (org-agenda-ng--add-markers)))))) (org-element-map tree types fun info first-match))) - ;;;; Faces/properties +(defun org-agenda-ng--add-markers (element) + "Return ELEMENT with marker properties added." + (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) + (properties (--> (second element) + (plist-put it :org-marker marker) + (plist-put it :org-hd-marker marker)))) + (setf (second element) properties) + element)) + (defun org-agenda-ng--format-element (element) ;; This essentially needs to do what `org-agenda-format-item' does, ;; which is a lot. We are a long way from that, but it's a start. @@ -112,7 +116,6 @@ Its property list should be the second item in the list, as returned by `org-ele (if-let ((marker (or (org-element-property :org-hd-marker element) (org-element-property :org-marker element)))) (org-with-point-at marker - (message "Getting tags for: %s" title) (org-get-tags-at)) ;; No marker found (warn "No marker found for item: %s" title) @@ -192,8 +195,6 @@ Its property list should be the second item in the list, as returned by `org-ele ;; No deadline element)) - - (defun org-agenda-ng--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) From a0f557d6fc08b312fe774a5fd1bb846c15c87357 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 06:04:04 -0500 Subject: [PATCH 013/970] Multi and stuff --- org-agenda-ng.el | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 4d5151e..ae01cbf 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -33,11 +33,31 @@ (read-only-mode 1) (pop-to-buffer (current-buffer))))) +(cl-defun org-agenda-ng--agenda-multi (&key files any-fns none-fns) + (let* ((entries (-flatten + (--map (org-agenda-ng--get-entries it + :any-fns any-fns + :none-fns none-fns) + files))) + (result-string (org-agenda-finalize-entries entries 'agenda)) + (target-buffer (get-buffer-create "test-agenda-ng"))) + (with-current-buffer target-buffer + (read-only-mode -1) + (erase-buffer) + (insert result-string) + (read-only-mode 1) + (pop-to-buffer (current-buffer))))) + (defmacro org-agenda-ng--test (&rest args) `(with-current-buffer (find-buffer-visiting "~/org/main.org") (org-agenda-ng--agenda ,@args))) +(defmacro org-agenda-ng--test-multi (&rest args) + `(org-agenda-ng--agenda-multi + :files '("~/org/main.org") + ,@args)) + (defun org-agenda-ng--test-agenda () (interactive) (org-agenda-ng--test @@ -46,20 +66,29 @@ (defun org-agenda-ng--test-agenda-today () (interactive) - (org-agenda-ng--test + (org-agenda-ng--test-multi :any-fns `((org-agenda-ng--date-p :date <= ,(org-today)) (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) + :none-fns `((org-agenda-ng--todo-p org-done-keywords)))) (defun org-agenda-ng--test-todo-list () (interactive) (org-agenda-ng--test :any-fns '(org-agenda-ng--todo-p) - :none-fns `((org-agenda-ng--todo-p ,org-done-keywords)))) + :none-fns '((org-agenda-ng--todo-p org-done-keywords)))) ;;;; Functions +(cl-defun org-agenda-ng--get-entries (file &key any-fns none-fns) + "Return list of entries from FILE." + (with-current-buffer (find-buffer-visiting file) + (let* ((org-use-tag-inheritance t) + (tree (cddr (org-element-parse-buffer 'headline))) + (entries (--> (org-agenda-ng--filter-tree tree :any-fns any-fns :none-fns none-fns) + (mapcar #'org-agenda-ng--format-element it)))) + entries))) + (cl-defun org-agenda-ng--filter-tree (tree &key any-fns none-fns) (let* ((types '(headline)) (info nil) @@ -211,6 +240,8 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (string= element-keyword keywords)) ((pred listp) (member element-keyword keywords)) + ((pred symbolp) + (member element-keyword (symbol-value keywords))) (otherwise (error "Invalid keyword argument: %s" otherwise))))) (defun org-agenda-ng--date-p (entry type &optional comparator target-date) From 4a79c834760c3abf7245a3ae5fc5ad0f6c1a69e5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 06:29:31 -0500 Subject: [PATCH 014/970] Add notes and stuff We can see that it's probably not worth it, because using the element parser is just too slow. --- notes.org | 294 +++++++++++++++++++++++++++++++++++++++++++++++ org-agenda-ng.el | 3 +- 2 files changed, 296 insertions(+), 1 deletion(-) create mode 100644 notes.org diff --git a/notes.org b/notes.org new file mode 100644 index 0000000..2cd029f --- /dev/null +++ b/notes.org @@ -0,0 +1,294 @@ + + +* Profiling + +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. + +** 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 + +#+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 diff --git a/org-agenda-ng.el b/org-agenda-ng.el index ae01cbf..4d8f8b4 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -34,6 +34,7 @@ (pop-to-buffer (current-buffer))))) (cl-defun org-agenda-ng--agenda-multi (&key files any-fns none-fns) + (mapc 'find-file-noselect files) (let* ((entries (-flatten (--map (org-agenda-ng--get-entries it :any-fns any-fns @@ -55,7 +56,7 @@ (defmacro org-agenda-ng--test-multi (&rest args) `(org-agenda-ng--agenda-multi - :files '("~/org/main.org") + :files org-agenda-files ,@args)) (defun org-agenda-ng--test-agenda () From 9721621223aabff2cc78a6ba99b20b5249e4274c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 5 Aug 2017 21:27:11 -0500 Subject: [PATCH 015/970] Add commentary --- org-agenda-ng.el | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 4d8f8b4..71af50d 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -1,5 +1,22 @@ ;;; Commentary: +;; This is just a proof-of-concept for how the agenda code might be +;; written in a more functional way, to avoid making multiple passes +;; through each file when building a multi-day agenda. + +;; Unfortunately, however, it's more like a proof-of-nope, because +;; it's significantly slower than the existing agenda code. Profiling +;; shows that =org-element-parse-buffer= is just not a fast function, +;; so most of the time spent is in that function, parsing the whole +;; buffer into a lisp tree. The existing agenda code is not written +;; in a functional style, and it makes multiple passes through each +;; file when preparing a multi-day agenda view, but it avoids parsing +;; the /entire/ buffer the way =org-element-parse-buffer= does. + +;; So I guess this approach won't work, unless someone can come up +;; with a version of =org-element-parse-buffer= that's about 10x +;; faster. + ;;;; Principles ;;;;; Work on elements From 7e5ee6bb0ba32e6eeccbb2fad0ab793baea147f5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 31 Dec 2017 17:56:42 -0600 Subject: [PATCH 016/970] Add idea --- notes.org | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/notes.org b/notes.org index 2cd029f..fc1d3f0 100644 --- a/notes.org +++ b/notes.org @@ -1,5 +1,11 @@ +* Ideas + +** Operate on list of heading positions + +[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. + * Profiling 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. From 9c3b78d6c4ec4cab36a9e788d128dec506ff158f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 06:17:15 -0600 Subject: [PATCH 017/970] Change: Use positions instead of parsing with org-element Now it's not slow. This may actually be useful now... --- org-agenda-ng.el | 277 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 187 insertions(+), 90 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 71af50d..874bbc3 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -34,28 +34,113 @@ (require 'dash) (require 'cl-lib) +;;;; Macros + +(cl-defun org-agenda-ng--test-lambda (&key all any none) + `(lambda () + (and ,@(-non-nil (list (when all + `(and ,@(--map (cl-typecase it + (function (list it)) + (cons `(apply #',(car it) ',(cdr it)))) + all))) + (when any + `(or ,@(--map (cl-typecase it + (function (list it)) + (cons `(apply #',(car it) ',(cdr it)))) + any))) + (when none + `(not (or ,@(--map (cl-typecase it + (function (list it)) + (cons `(apply #',(car it) ',(cdr it)))) + none))))))))) + +;;;; Tests + +(defun org-agenda-ng--test-test.org (&rest args) + ;; Helper function + (apply #'org-agenda-ng--agenda :files '("~/src/emacs/org-super-agenda/test/test.org") + args)) + +(defun org-agenda-ng--test-agenda () + (interactive) + (org-agenda-ng--test-test.org + :any '((org-agenda-ng--todo-p "TODO") + (org-agenda-ng--date-p :deadline < "2017-08-05")))) + +(defun org-agenda-ng--test-agenda2 () + (interactive) + (org-agenda-ng--test-test.org + :any `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none `((org-agenda-ng--todo-p org-done-keywords)))) + +(defun org-agenda-ng--test-agenda3 () + (interactive) + (org-agenda-ng--test-test.org + :any `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none `((org-agenda-ng--todo-p org-done-keywords)))) + +(defun org-agenda-ng--test-agenda-today () + (interactive) + (org-agenda-ng--agenda + :files "~/src/emacs/org-super-agenda/test/test.org" + :any `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none `((org-agenda-ng--todo-p org-done-keywords)))) + +(defun org-agenda-ng--test-agenda-today () + (interactive) + (org-agenda-ng--agenda + :files "~/src/emacs/org-super-agenda/test/test.org" + :any `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none `((org-agenda-ng--todo-p org-done-keywords)))) + +(defun org-agenda-ng--test-agenda-today () + (interactive) + (org-agenda-ng--agenda + :files org-agenda-files + :any `((org-agenda-ng--date-p :date <= ,(org-today)) + (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) + (org-agenda-ng--date-p :scheduled <= ,(org-today))) + :none `((org-agenda-ng--todo-p org-done-keywords)))) + +(defun org-agenda-ng--test-todo-list () + (interactive) + (org-agenda-ng--test-test.org + :any '(org-agenda-ng--todo-p) + :none '((org-agenda-ng--todo-p org-done-keywords)))) + ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key any-fns none-fns) - (let* ((org-use-tag-inheritance t) - (tree (cddr (org-element-parse-buffer 'headline))) - (entries (--> (org-agenda-ng--filter-tree tree :any-fns any-fns :none-fns none-fns) - (mapcar #'org-agenda-ng--format-element it))) - (result-string (org-agenda-finalize-entries entries 'agenda)) - (target-buffer (get-buffer-create "test-agenda-ng"))) - (with-current-buffer target-buffer - (read-only-mode -1) - (erase-buffer) - (insert result-string) - (read-only-mode 1) - (pop-to-buffer (current-buffer))))) - -(cl-defun org-agenda-ng--agenda-multi (&key files any-fns none-fns) +(cl-defun org-agenda-ng--agenda (&key files all any none) + (unless files + (setq files (buffer-file-name (current-buffer)))) + (unless (listp files) + (setq files (list files))) (mapc 'find-file-noselect files) - (let* ((entries (-flatten - (--map (org-agenda-ng--get-entries it - :any-fns any-fns - :none-fns none-fns) + (let* ((org-use-tag-inheritance t) + (entries (-flatten + (--map (with-current-buffer (find-buffer-visiting it) + ;; FIXME: It would be more optimal to + ;; gather the entry at each matching + ;; position instead of returning a list of + ;; positions and then having to go back + ;; and get the entries at each position. + (let* ((positions (org-agenda-ng--filter-buffer :all all :any any :none none)) + (elements (--map (org-with-point-at it + (org-element-headline-parser + ;; FIXME: This is a hack + (save-excursion + (forward-line 3) + (point)))) + positions))) + (mapcar #'org-agenda-ng--format-element elements))) files))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) @@ -66,66 +151,62 @@ (read-only-mode 1) (pop-to-buffer (current-buffer))))) -(defmacro org-agenda-ng--test (&rest args) - `(with-current-buffer (find-buffer-visiting "~/org/main.org") - (org-agenda-ng--agenda - ,@args))) - -(defmacro org-agenda-ng--test-multi (&rest args) - `(org-agenda-ng--agenda-multi - :files org-agenda-files - ,@args)) - -(defun org-agenda-ng--test-agenda () - (interactive) - (org-agenda-ng--test - :any-fns '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--date-p :deadline < "2017-08-05")))) - -(defun org-agenda-ng--test-agenda-today () - (interactive) - (org-agenda-ng--test-multi - :any-fns `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none-fns `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-todo-list () - (interactive) - (org-agenda-ng--test - :any-fns '(org-agenda-ng--todo-p) - :none-fns '((org-agenda-ng--todo-p org-done-keywords)))) - ;;;; Functions -(cl-defun org-agenda-ng--get-entries (file &key any-fns none-fns) - "Return list of entries from FILE." - (with-current-buffer (find-buffer-visiting file) - (let* ((org-use-tag-inheritance t) - (tree (cddr (org-element-parse-buffer 'headline))) - (entries (--> (org-agenda-ng--filter-tree tree :any-fns any-fns :none-fns none-fns) - (mapcar #'org-agenda-ng--format-element it)))) - entries))) +;; (cl-defun org-agenda-ng--get-entries (file &key any-preds none-preds) +;; "Return list of entries from FILE." +;; (with-current-buffer (find-buffer-visiting file) +;; (let* ((org-use-tag-inheritance t) +;; (tree (cddr (org-element-parse-buffer 'headline))) +;; (entries (--> (org-agenda-ng--filter-tree tree :any any-preds :none none-preds) +;; (mapcar #'org-agenda-ng--format-element it)))) +;; entries))) -(cl-defun org-agenda-ng--filter-tree (tree &key any-fns none-fns) - (let* ((types '(headline)) - (info nil) - (first-match nil) - (fun (lambda (element) - (when (and (--any? (cl-typecase it - (function (funcall it element)) - (cons (apply (car it) element (cdr it)))) - any-fns) - ;; Don't return if any filters match - (or (null none-fns) - (--none? (cl-typecase it - (function (funcall it element)) - (cons (apply (car it) element (cdr it)))) - none-fns))) - ;; Return element - (->> element - (org-agenda-ng--add-markers)))))) - (org-element-map tree types fun info first-match))) +(cl-defun org-agenda-ng--heading-positions (file) + "Return list of heading positions in FILE." + (with-current-buffer (find-buffer-visiting file) + (save-excursion + (goto-char (point-min)) + (cl-loop initially do (when (org-before-first-heading-p) + (outline-next-heading)) + collect (point) + while (outline-next-heading))))) + +;; (cl-defun org-agenda-ng--filter-buffer (&key any-preds none-preds) +;; "Return positions of matching headings in current buffer. +;; Headings should return non-nil for any ANY-PREDS and nil for all +;; NONE-PREDS." +;; (cl-flet ((pred () (and (--any? (cl-typecase it +;; (function (funcall it)) +;; (cons (apply (car it) (cdr it)))) +;; any-preds) +;; ;; Don't return if any filters match +;; (or (null none-preds) +;; (--none? (cl-typecase it +;; (function (funcall it)) +;; (cons (apply (car it) (cdr it)))) +;; none-preds))))) +;; (org-with-wide-buffer +;; (goto-char (point-min)) +;; (when (org-before-first-heading-p) +;; (outline-next-heading)) +;; (cl-loop when (pred) +;; collect (point) +;; while (outline-next-heading))))) + +(cl-defun org-agenda-ng--filter-buffer (&key all any none) + "Return positions of matching headings in current buffer. +Headings should return non-nil for any ANY-PREDS and nil for all +NONE-PREDS." + ;; NOTE: Build lambda so typecase doesn't run for every item + (let ((pred (org-agenda-ng--test-lambda :all all :any any :none none))) + (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (point) + while (outline-next-heading))))) ;;;; Faces/properties @@ -155,13 +236,15 @@ Its property list should be the second item in the list, as returned by `org-ele unless (member key '(parent)) append (list key val))) (title (--> (org-agenda-ng--add-faces element) - (org-element-property :title it) - (org-link-display-format it))) + (org-element-property :raw-value it) + ;; (org-link-display-format it) + )) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) (tag-list (if org-agenda-use-tag-inheritance (if-let ((marker (or (org-element-property :org-hd-marker element) - (org-element-property :org-marker element)))) + (org-element-property :org-marker element) + (org-element-property :begin element)))) (org-with-point-at marker (org-get-tags-at)) ;; No marker found @@ -182,6 +265,7 @@ Its property list should be the second item in the list, as returned by `org-ele (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string + (concat " " it) (org-add-props it properties 'tags tag-list)))) (defun org-agenda-ng--add-faces (element) @@ -208,7 +292,7 @@ Its property list should be the second item in the list, as returned by `org-ele (done-p 'org-agenda-done) (today-p 'org-scheduled-today) (t 'org-scheduled))) - (title (--> (org-element-property :title element) + (title (--> (org-element-property :raw-value element) (org-add-props it nil 'face face))) (properties (--> (second element) @@ -232,7 +316,7 @@ Its property list should be the second item in the list, as returned by `org-ele (/ it (max org-deadline-warning-days 1)) (- 1 it))) (face (org-agenda-deadline-face deadline-passed-fraction)) - (title (--> (org-element-property :title element) + (title (--> (org-element-property :raw-value element) (org-add-props it nil 'face face))) (properties (--> (second element) @@ -248,29 +332,42 @@ Its property list should be the second item in the list, as returned by `org-ele ;;;; Predicates -(defun org-agenda-ng--todo-p (element &optional keywords) - "Return non-nil if ELEMENT is a TODO item. +(defun org-agenda-ng--todo-p (keywords &rest more) + "Return non-nil if current heading is a TODO item. With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." - (when-let ((element-keyword (org-element-property :todo-keyword element))) + (when more + (cons more keywords)) + (when-let ((state (org-get-todo-state))) (pcase keywords ('nil t) ((pred stringp) - (string= element-keyword keywords)) + (string= state keywords)) ((pred listp) - (member element-keyword keywords)) + (member state keywords)) ((pred symbolp) - (member element-keyword (symbol-value keywords))) + (member state (symbol-value keywords))) (otherwise (error "Invalid keyword argument: %s" otherwise))))) -(defun org-agenda-ng--date-p (entry type &optional comparator target-date) - "Return non-nil if ENTRY has a date property of TYPE. +(defun org-agenda-ng--date-p (type &optional comparator target-date) + "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. With COMPARATOR and TARGET-DATE, return non-nil if entry's scheduled date compares with TARGET-DATE according to COMPARATOR. TARGET-DATE may be a string like \"2017-08-05\", or an integer like one returned by `date-to-day'." - (when-let ((entry-date (org-element-property type entry))) + (when-let ((entry-date (awhen (pcase type + (:deadline (org-entry-get (point) "DEADLINE")) + (:scheduled (org-entry-get (point) "SCHEDULED"))) + ;; FIXME: Hack: since we're using + ;; (org-element-property :type entry-date) + ;; below, we need this date parsed into an + ;; org-element element + (with-temp-buffer + (insert it) + (goto-char 0) + (org-element-timestamp-parser)) + ))) (pcase comparator ;; Not comparing, just checking if it has one ('nil t) From 0abe04b916815c8c6517bf71466c589be5eee0da Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 06:58:49 -0600 Subject: [PATCH 018/970] A few improvements --- org-agenda-ng.el | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 874bbc3..95454ea 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -1,3 +1,6 @@ +;; -*- lexical-binding: t; -*- + + ;;; Commentary: ;; This is just a proof-of-concept for how the agenda code might be @@ -118,7 +121,7 @@ ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key files all any none) +(cl-defun org-agenda-ng--agenda (&key files all any none pred) (unless files (setq files (buffer-file-name (current-buffer)))) (unless (listp files) @@ -132,7 +135,7 @@ ;; position instead of returning a list of ;; positions and then having to go back ;; and get the entries at each position. - (let* ((positions (org-agenda-ng--filter-buffer :all all :any any :none none)) + (let* ((positions (org-agenda-ng--filter-buffer :all all :any any :none none :pred pred)) (elements (--map (org-with-point-at it (org-element-headline-parser ;; FIXME: This is a hack @@ -194,12 +197,20 @@ ;; collect (point) ;; while (outline-next-heading))))) -(cl-defun org-agenda-ng--filter-buffer (&key all any none) +(cl-defun org-agenda-ng--filter-buffer (&key all any none pred) "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." ;; NOTE: Build lambda so typecase doesn't run for every item - (let ((pred (org-agenda-ng--test-lambda :all all :any any :none none))) + (let* ((our-lambda (when (or all any none) + (org-agenda-ng--test-lambda :all all :any any :none none))) + (pred (cond ((and our-lambda pred) + (lambda () + (and (funcall our-lambda) + (funcall pred)))) + (our-lambda our-lambda) + (pred pred) + (t (user-error "No tests given"))))) (org-with-wide-buffer (goto-char (point-min)) (when (org-before-first-heading-p) @@ -332,16 +343,14 @@ Its property list should be the second item in the list, as returned by `org-ele ;;;; Predicates -(defun org-agenda-ng--todo-p (keywords &rest more) +(defun org-agenda-ng--todo-p (&rest keywords) "Return non-nil if current heading is a TODO item. With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." - (when more - (cons more keywords)) (when-let ((state (org-get-todo-state))) (pcase keywords ('nil t) - ((pred stringp) - (string= state keywords)) + ;; ((pred stringp) + ;; (string= state keywords)) ((pred listp) (member state keywords)) ((pred symbolp) From e25332b933f89e46ca1c815a33b0e3f4f731dbf5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 08:12:54 -0600 Subject: [PATCH 019/970] Use cl-letf to allow shorter function names in tests --- org-agenda-ng.el | 74 +++++++++++++++++------------------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 95454ea..573fa28 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -39,7 +39,15 @@ ;;;; Macros +(defmacro org-agenda-ng--flet (fns &rest body) + (declare (indent defun)) + `(cl-letf ,(cl-loop for (fn def) in fns + collect `((symbol-function ',fn) + ,def)) + ,@body)) + (cl-defun org-agenda-ng--test-lambda (&key all any none) + ;; Not actually a macro, but... `(lambda () (and ,@(-non-nil (list (when all `(and ,@(--map (cl-typecase it @@ -156,15 +164,6 @@ ;;;; Functions -;; (cl-defun org-agenda-ng--get-entries (file &key any-preds none-preds) -;; "Return list of entries from FILE." -;; (with-current-buffer (find-buffer-visiting file) -;; (let* ((org-use-tag-inheritance t) -;; (tree (cddr (org-element-parse-buffer 'headline))) -;; (entries (--> (org-agenda-ng--filter-tree tree :any any-preds :none none-preds) -;; (mapcar #'org-agenda-ng--format-element it)))) -;; entries))) - (cl-defun org-agenda-ng--heading-positions (file) "Return list of heading positions in FILE." (with-current-buffer (find-buffer-visiting file) @@ -175,49 +174,28 @@ collect (point) while (outline-next-heading))))) -;; (cl-defun org-agenda-ng--filter-buffer (&key any-preds none-preds) -;; "Return positions of matching headings in current buffer. -;; Headings should return non-nil for any ANY-PREDS and nil for all -;; NONE-PREDS." -;; (cl-flet ((pred () (and (--any? (cl-typecase it -;; (function (funcall it)) -;; (cons (apply (car it) (cdr it)))) -;; any-preds) -;; ;; Don't return if any filters match -;; (or (null none-preds) -;; (--none? (cl-typecase it -;; (function (funcall it)) -;; (cons (apply (car it) (cdr it)))) -;; none-preds))))) -;; (org-with-wide-buffer -;; (goto-char (point-min)) -;; (when (org-before-first-heading-p) -;; (outline-next-heading)) -;; (cl-loop when (pred) -;; collect (point) -;; while (outline-next-heading))))) - (cl-defun org-agenda-ng--filter-buffer (&key all any none pred) "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." - ;; NOTE: Build lambda so typecase doesn't run for every item - (let* ((our-lambda (when (or all any none) - (org-agenda-ng--test-lambda :all all :any any :none none))) - (pred (cond ((and our-lambda pred) - (lambda () - (and (funcall our-lambda) - (funcall pred)))) - (our-lambda our-lambda) - (pred pred) - (t (user-error "No tests given"))))) - (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (point) - while (outline-next-heading))))) + (org-agenda-ng--flet ((date (lambda (&rest args) (apply #'org-agenda-ng--date-p args))) + (todo (lambda (&rest args) (apply #'org-agenda-ng--todo-p args)))) + (let* ((our-lambda (when (or all any none) + (org-agenda-ng--test-lambda :all all :any any :none none))) + (pred (cond ((and our-lambda pred) + (lambda () + (and (funcall our-lambda) + (funcall pred)))) + (our-lambda our-lambda) + (pred pred) + (t (user-error "No tests given"))))) + (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (point) + while (outline-next-heading)))))) ;;;; Faces/properties From 24326c05fa903cd65ce4e38bbbfcaf5e9e778ee0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 09:38:48 -0600 Subject: [PATCH 020/970] More stuff --- org-agenda-ng.el | 114 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 15 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 573fa28..4ad010d 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -36,6 +36,7 @@ (require 'org-agenda) (require 'dash) (require 'cl-lib) +(require 'seq) ;;;; Macros @@ -65,6 +66,12 @@ (cons `(apply #',(car it) ',(cdr it)))) none))))))))) +(cl-defmacro org-agenda-ng (files &rest pred) + (declare (indent defun)) + `(org-agenda-ng--agenda :files ,files + :pred (lambda () + ,@pred))) + ;;;; Tests (defun org-agenda-ng--test-test.org (&rest args) @@ -178,8 +185,10 @@ "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." - (org-agenda-ng--flet ((date (lambda (&rest args) (apply #'org-agenda-ng--date-p args))) - (todo (lambda (&rest args) (apply #'org-agenda-ng--todo-p args)))) + (org-agenda-ng--flet ((category (lambda (&rest args) (apply #'org-agenda-ng--category-p args))) + (date (lambda (&rest args) (apply #'org-agenda-ng--date-p args))) + (todo (lambda (&rest args) (apply #'org-agenda-ng--todo-p args))) + (tags (lambda (&rest args) (apply #'org-agenda-ng--tags-p args)))) (let* ((our-lambda (when (or all any none) (org-agenda-ng--test-lambda :all all :any any :none none))) (pred (cond ((and our-lambda pred) @@ -275,11 +284,10 @@ Its property list should be the second item in the list, as returned by `org-ele (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) (todo-keyword (org-element-property :todo-keyword element)) - (done-p (member todo-keyword org-done-keywords)) - (today-p (= today-day-number scheduled-day-number)) (face (cond - (done-p 'org-agenda-done) - (today-p 'org-scheduled-today) + ((member todo-keyword org-done-keywords) 'org-agenda-done) + ((= today-day-number scheduled-day-number) 'org-scheduled-today) + ((> today-day-number scheduled-day-number) 'org-scheduled-previously) (t 'org-scheduled))) (title (--> (org-element-property :raw-value element) (org-add-props it nil @@ -291,6 +299,68 @@ Its property list should be the second item in the list, as returned by `org-ele ;; Not scheduled element)) +(defun org-agenda-ng--add-scheduled-face (element) + "Add faces to ELEMENT's title for its scheduled status." + ;; NOTE: Also adding prefix + (if-let ((scheduled-date (org-element-property :scheduled element))) + (let* ((show-all (or (eq org-agenda-repeating-timestamp-show-all t) + (member todo-keyword org-agenda-repeating-timestamp-show-all))) + (raw-value (org-element-property :raw-value scheduled-date)) + (sexp-p (string-prefix-p "%%" raw-value)) + (today-day-number (org-today)) + (current-day-number + ;; FIXME: This is supposed to be the, shall we say, + ;; pretend, or perspective, day number that this pass + ;; through the agenda is being made for. We need to + ;; either set this in the calling function, set it here, + ;; or accomplish this in a different way. See + ;; `org-agenda-get-scheduled' and where `date' is set in + ;; `org-agenda-list'. + today-day-number) + (scheduled-day-number (org-time-string-to-absolute + (org-element-timestamp-interpreter scheduled-date 'ignore))) + (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) + ((< today-day-number scheduled-day-number) scheduled-day-number) + (t (org-time-string-to-absolute + raw-value + (if show-all + current-day-number + today-day-number) + 'future + ;; FIXME: I don't like + ;; calling `current-buffer' + ;; here. If the element has + ;; a marker, we should use + ;; that. + (current-buffer) + (org-element-property :begin element))))) + (todo-keyword (org-element-property :todo-keyword element)) + (face (cond ((member todo-keyword org-done-keywords) 'org-agenda-done) + ((= today-day-number scheduled-day-number) 'org-scheduled-today) + ((> today-day-number scheduled-day-number) 'org-scheduled-previously) + (t 'org-scheduled))) + (title (--> (org-element-property :raw-value element) + (org-add-props it nil + 'face face))) + (properties (--> (second element) + (plist-put it :title title))) + (prefix (cl-destructuring-bind (first next) org-agenda-scheduled-leaders + (cond ((> scheduled-day-number today-day-number) + ;; Future + first) + ((and (not show-all) + (= repeat today-day-number))) + ((= today-day-number scheduled-day-number) + ;; Today + first) + (t + ;; Subsequent reminders. Count from base schedule. + (format next (1+ (- today-day-number scheduled-day-number)))))))) + (list (car element) + properties)) + ;; Not scheduled + element)) + (defun org-agenda-ng--add-deadline-face (element) "Add faces to ELEMENT's title for its deadline status." (if-let ((deadline-date (org-element-property :deadline element))) @@ -321,19 +391,33 @@ Its property list should be the second item in the list, as returned by `org-ele ;;;; Predicates +(defun org-agenda-ng--category-p (&rest categories) + "Return non-nil if current heading is in one or more of CATEGORIES." + (when-let ((category (org-get-category (point)))) + (cl-typecase categories + (null t) + (otherwise (member category categories))))) + (defun org-agenda-ng--todo-p (&rest keywords) "Return non-nil if current heading is a TODO item. With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (when-let ((state (org-get-todo-state))) - (pcase keywords - ('nil t) - ;; ((pred stringp) - ;; (string= state keywords)) - ((pred listp) - (member state keywords)) - ((pred symbolp) - (member state (symbol-value keywords))) - (otherwise (error "Invalid keyword argument: %s" otherwise))))) + (cl-typecase keywords + (null t) + (list (member state keywords)) + (symbol (member state (symbol-value keywords))) + (otherwise (user-error "Invalid todo keywords: %s" keywords))))) + +(defun org-agenda-ng--tags-p (&rest tags) + "Return non-nil if current heading has TAGS." + ;; TODO: Try to use `org-make-tags-matcher' to improve performance. + (when-let ((tags-at (org-get-tags-at (point) + ;; FIXME: Would be nice to not check this for every heading checked. + ;; (not (member 'agenda org-agenda-use-tag-inheritance)) + ))) + (cl-typecase tags + (null t) + (otherwise (seq-intersection tags tags-at))))) (defun org-agenda-ng--date-p (type &optional comparator target-date) "Return non-nil if current heading has a date property of TYPE. From 8fcbd8de0fbaa2c7884e2eafa332b41d78b693c7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 10:28:40 -0600 Subject: [PATCH 021/970] And more --- README.org | 29 +++++++++++++++++++++++++++++ org-agenda-ng.el | 44 +++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 README.org diff --git a/README.org b/README.org new file mode 100644 index 0000000..a0fa029 --- /dev/null +++ b/README.org @@ -0,0 +1,29 @@ +This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does. But it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. + +Here's an example of generating a kind of agenda view for today: + +#+BEGIN_SRC elisp + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (and (or (date :deadline '<= (org-today)) + (date :scheduled '<= (org-today))) + (not (apply #'todo org-done-keywords-for-agenda)))) +#+END_SRC + +Here are some other examples: + +#+BEGIN_SRC elisp + (org-agenda-ng org-agenda-files + (and (todo "TODO" "SOMEDAY") + (tags "computer" "Emacs") + (category "main"))) + + (org-agenda-ng org-agenda-files + (habit)) + + (org-agenda-ng "~/org/main.org" + (or (habit) + (date :deadline '<= (org-today)) + (date :scheduled '<= (org-today)) + (and (todo "DONE" "CANCELLED") + (date :closed '= (org-today))))) +#+END_SRC diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 4ad010d..7dce4b4 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -167,7 +167,8 @@ (erase-buffer) (insert result-string) (read-only-mode 1) - (pop-to-buffer (current-buffer))))) + (pop-to-buffer (current-buffer)) + (org-agenda-finalize)))) ;;;; Functions @@ -187,6 +188,7 @@ Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." (org-agenda-ng--flet ((category (lambda (&rest args) (apply #'org-agenda-ng--category-p args))) (date (lambda (&rest args) (apply #'org-agenda-ng--date-p args))) + (habit (lambda (&rest args) (apply #'org-agenda-ng--habit-p args))) (todo (lambda (&rest args) (apply #'org-agenda-ng--todo-p args))) (tags (lambda (&rest args) (apply #'org-agenda-ng--tags-p args)))) (let* ((our-lambda (when (or all any none) @@ -235,7 +237,7 @@ Its property list should be the second item in the list, as returned by `org-ele append (list key val))) (title (--> (org-agenda-ng--add-faces element) (org-element-property :raw-value it) - ;; (org-link-display-format it) + (org-link-display-format it) )) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) @@ -259,12 +261,18 @@ Its property list should be the second item in the list, as returned by `org-ele (char-to-string) (format "[#%s]") (org-agenda-ng--add-priority-face))) + (habit-property (org-with-point-at (org-element-property :begin element) + (when (org-is-habit-p) + (org-habit-parse-todo)))) (string (s-join " " (list todo-keyword priority-string title tag-string)))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string (concat " " it) - (org-add-props it properties 'tags tag-list)))) + (org-add-props it properties + 'todo-state todo-keyword + 'tags tag-list + 'org-habit-p habit-property)))) (defun org-agenda-ng--add-faces (element) (->> element @@ -413,8 +421,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." ;; TODO: Try to use `org-make-tags-matcher' to improve performance. (when-let ((tags-at (org-get-tags-at (point) ;; FIXME: Would be nice to not check this for every heading checked. - ;; (not (member 'agenda org-agenda-use-tag-inheritance)) - ))) + (not (member 'agenda org-agenda-use-tag-inheritance))))) (cl-typecase tags (null t) (otherwise (seq-intersection tags tags-at))))) @@ -427,18 +434,18 @@ With COMPARATOR and TARGET-DATE, return non-nil if entry's scheduled date compares with TARGET-DATE according to COMPARATOR. TARGET-DATE may be a string like \"2017-08-05\", or an integer like one returned by `date-to-day'." - (when-let ((entry-date (awhen (pcase type - (:deadline (org-entry-get (point) "DEADLINE")) - (:scheduled (org-entry-get (point) "SCHEDULED"))) + (when-let ((timestamp (pcase type + (:deadline (org-entry-get (point) "DEADLINE")) + (:scheduled (org-entry-get (point) "SCHEDULED")) + (:closed (org-entry-get (point) "CLOSED")))) + (date-element (with-temp-buffer ;; FIXME: Hack: since we're using - ;; (org-element-property :type entry-date) + ;; (org-element-property :type date-element) ;; below, we need this date parsed into an ;; org-element element - (with-temp-buffer - (insert it) - (goto-char 0) - (org-element-timestamp-parser)) - ))) + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)))) (pcase comparator ;; Not comparing, just checking if it has one ('nil t) @@ -449,11 +456,14 @@ like one returned by `date-to-day'." ;; because `date-to-day' requires it (string (date-to-day (concat target-date " 00:00"))) (integer target-date)))) - (pcase (org-element-property :type entry-date) + (pcase (org-element-property :type date-element) ((or 'active 'inactive) (funcall comparator (org-time-string-to-absolute - (org-element-timestamp-interpreter entry-date 'ignore)) + (org-element-timestamp-interpreter date-element 'ignore)) target-day-number)) - (error "Unknown entry-date type: %s" (org-element-property :type entry-date))))) + (error "Unknown date-element type: %s" (org-element-property :type date-element))))) (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) + +(defun org-agenda-ng--habit-p () + (org-is-habit-p)) From f0811a9220d8e1557e8b33453b6bd5f7e181d6c3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 10:32:40 -0600 Subject: [PATCH 022/970] More --- README.org | 7 +++++-- screenshot.png | Bin 0 -> 48041 bytes 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 screenshot.png diff --git a/README.org b/README.org index a0fa029..ed66f25 100644 --- a/README.org +++ b/README.org @@ -1,14 +1,17 @@ -This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does. But it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. +This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does, but it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. Here's an example of generating a kind of agenda view for today: #+BEGIN_SRC elisp (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date :deadline '<= (org-today)) + (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 +[[screenshot.png]] + Here are some other examples: #+BEGIN_SRC elisp diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..9a1b7c86a0fb494158bb23991b33006dd70f8066 GIT binary patch literal 48041 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 Date: Wed, 3 Jan 2018 10:39:52 -0600 Subject: [PATCH 023/970] Add note --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index ed66f25..d5ada05 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,6 @@ This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does, but it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. -Here's an example of generating a kind of agenda view for today: +Here's an example of generating a kind of agenda view for today (note that the grouping is provided by [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], not this code: #+BEGIN_SRC elisp (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" From e6b4b5223bf4676967a574e9c5b0c455aceb96a3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 10:41:47 -0600 Subject: [PATCH 024/970] Add fixme --- org-agenda-ng.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 7dce4b4..f503abc 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -435,6 +435,9 @@ scheduled date compares with TARGET-DATE according to COMPARATOR. TARGET-DATE may be a string like \"2017-08-05\", or an integer like one returned by `date-to-day'." (when-let ((timestamp (pcase type + ;; FIXME: Add :date selector, since I put it + ;; in the examples but forgot to actually + ;; make it. (:deadline (org-entry-get (point) "DEADLINE")) (:scheduled (org-entry-get (point) "SCHEDULED")) (:closed (org-entry-get (point) "CLOSED")))) From 090f77ece97faa72d439e06deeb3f15637ff632a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:00:30 -0600 Subject: [PATCH 025/970] Prune --- org-agenda-ng.el | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index f503abc..e01987f 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -285,28 +285,6 @@ Its property list should be the second item in the list, as returned by `org-ele (let ((face (org-get-priority-face (string-to-char (match-string 2))))) (org-add-props string nil 'face face 'font-lock-fontified t)))) -(defun org-agenda-ng--add-scheduled-face (element) - "Add faces to ELEMENT's title for its scheduled status." - (if-let ((scheduled-date (org-element-property :scheduled element))) - (let* ((today-day-number (org-today)) - (scheduled-day-number (org-time-string-to-absolute - (org-element-timestamp-interpreter scheduled-date 'ignore))) - (todo-keyword (org-element-property :todo-keyword element)) - (face (cond - ((member todo-keyword org-done-keywords) 'org-agenda-done) - ((= today-day-number scheduled-day-number) 'org-scheduled-today) - ((> today-day-number scheduled-day-number) 'org-scheduled-previously) - (t 'org-scheduled))) - (title (--> (org-element-property :raw-value element) - (org-add-props it nil - 'face face))) - (properties (--> (second element) - (plist-put it :title title)))) - (list (car element) - properties)) - ;; Not scheduled - element)) - (defun org-agenda-ng--add-scheduled-face (element) "Add faces to ELEMENT's title for its scheduled status." ;; NOTE: Also adding prefix From 38d549e6ccfff178bbb2f6b2056bbeab1acec2cc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:08:12 -0600 Subject: [PATCH 026/970] Add notes --- org-agenda-ng.el | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e01987f..f81c799 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -183,6 +183,7 @@ while (outline-next-heading))))) (cl-defun org-agenda-ng--filter-buffer (&key all any none pred) + ;; TODO: Remove all, any, and none, and just use the predicate lambda. "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." @@ -229,8 +230,12 @@ Its property list should be the second item in the list, as returned by `org-ele ;; the properties list that it makes it essentially ;; impossible to debug, because Emacs takes approximately ;; forever to show it in the minibuffer or with - ;; `describe-text-properties'. Also, remove ":" from key - ;; symbols. + ;; `describe-text-properties'. FIXME: Shouldn't be necessary + ;; anymore since we're not parsing the whole buffer. + + ;; Also, remove ":" from key symbols. FIXME: It would be + ;; better to avoid this somehow. At least, we should use a + ;; function to convert plists to alists, if possible. (properties (cl-loop for (key val) on properties by #'cddr for key = (intern (cl-subseq (symbol-name key) 1)) unless (member key '(parent)) @@ -268,6 +273,7 @@ Its property list should be the second item in the list, as returned by `org-ele (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string + ;; FIXME: Use proper prefix (concat " " it) (org-add-props it properties 'todo-state todo-keyword From c412012100472c2f199636aeb3d846954e4dc1b8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:10:02 -0600 Subject: [PATCH 027/970] flet->fmap --- org-agenda-ng.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index f81c799..44e76ef 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -40,11 +40,11 @@ ;;;; Macros -(defmacro org-agenda-ng--flet (fns &rest body) +(defmacro org-agenda-ng--fmap (fns &rest body) (declare (indent defun)) - `(cl-letf ,(cl-loop for (fn def) in fns + `(cl-letf ,(cl-loop for (fn target) in fns collect `((symbol-function ',fn) - ,def)) + (symbol-function ,target))) ,@body)) (cl-defun org-agenda-ng--test-lambda (&key all any none) @@ -187,11 +187,11 @@ "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." - (org-agenda-ng--flet ((category (lambda (&rest args) (apply #'org-agenda-ng--category-p args))) - (date (lambda (&rest args) (apply #'org-agenda-ng--date-p args))) - (habit (lambda (&rest args) (apply #'org-agenda-ng--habit-p args))) - (todo (lambda (&rest args) (apply #'org-agenda-ng--todo-p args))) - (tags (lambda (&rest args) (apply #'org-agenda-ng--tags-p args)))) + (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) + (date #'org-agenda-ng--date-p) + (habit #'org-agenda-ng--habit-p) + (todo #'org-agenda-ng--todo-p) + (tags #'org-agenda-ng--tags-p)) (let* ((our-lambda (when (or all any none) (org-agenda-ng--test-lambda :all all :any any :none none))) (pred (cond ((and our-lambda pred) From 1976319ed85a28e9637d714f1db934089323f883 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:14:03 -0600 Subject: [PATCH 028/970] Prune --- org-agenda-ng.el | 114 +++++------------------------------------------ 1 file changed, 12 insertions(+), 102 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 44e76ef..e03203c 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -47,96 +47,15 @@ (symbol-function ,target))) ,@body)) -(cl-defun org-agenda-ng--test-lambda (&key all any none) - ;; Not actually a macro, but... - `(lambda () - (and ,@(-non-nil (list (when all - `(and ,@(--map (cl-typecase it - (function (list it)) - (cons `(apply #',(car it) ',(cdr it)))) - all))) - (when any - `(or ,@(--map (cl-typecase it - (function (list it)) - (cons `(apply #',(car it) ',(cdr it)))) - any))) - (when none - `(not (or ,@(--map (cl-typecase it - (function (list it)) - (cons `(apply #',(car it) ',(cdr it)))) - none))))))))) - -(cl-defmacro org-agenda-ng (files &rest pred) +(cl-defmacro org-agenda-ng (files &rest pred-body) (declare (indent defun)) `(org-agenda-ng--agenda :files ,files :pred (lambda () - ,@pred))) - -;;;; Tests - -(defun org-agenda-ng--test-test.org (&rest args) - ;; Helper function - (apply #'org-agenda-ng--agenda :files '("~/src/emacs/org-super-agenda/test/test.org") - args)) - -(defun org-agenda-ng--test-agenda () - (interactive) - (org-agenda-ng--test-test.org - :any '((org-agenda-ng--todo-p "TODO") - (org-agenda-ng--date-p :deadline < "2017-08-05")))) - -(defun org-agenda-ng--test-agenda2 () - (interactive) - (org-agenda-ng--test-test.org - :any `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-agenda3 () - (interactive) - (org-agenda-ng--test-test.org - :any `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-agenda-today () - (interactive) - (org-agenda-ng--agenda - :files "~/src/emacs/org-super-agenda/test/test.org" - :any `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-agenda-today () - (interactive) - (org-agenda-ng--agenda - :files "~/src/emacs/org-super-agenda/test/test.org" - :any `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-agenda-today () - (interactive) - (org-agenda-ng--agenda - :files org-agenda-files - :any `((org-agenda-ng--date-p :date <= ,(org-today)) - (org-agenda-ng--date-p :deadline <= ,(+ org-deadline-warning-days (org-today))) - (org-agenda-ng--date-p :scheduled <= ,(org-today))) - :none `((org-agenda-ng--todo-p org-done-keywords)))) - -(defun org-agenda-ng--test-todo-list () - (interactive) - (org-agenda-ng--test-test.org - :any '(org-agenda-ng--todo-p) - :none '((org-agenda-ng--todo-p org-done-keywords)))) + ,@pred-body))) ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key files all any none pred) +(cl-defun org-agenda-ng--agenda (&key files pred) (unless files (setq files (buffer-file-name (current-buffer)))) (unless (listp files) @@ -150,7 +69,7 @@ ;; position instead of returning a list of ;; positions and then having to go back ;; and get the entries at each position. - (let* ((positions (org-agenda-ng--filter-buffer :all all :any any :none none :pred pred)) + (let* ((positions (org-agenda-ng--filter-buffer :pred pred)) (elements (--map (org-with-point-at it (org-element-headline-parser ;; FIXME: This is a hack @@ -182,7 +101,7 @@ collect (point) while (outline-next-heading))))) -(cl-defun org-agenda-ng--filter-buffer (&key all any none pred) +(cl-defun org-agenda-ng--filter-buffer (&key pred) ;; TODO: Remove all, any, and none, and just use the predicate lambda. "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all @@ -192,22 +111,13 @@ NONE-PREDS." (habit #'org-agenda-ng--habit-p) (todo #'org-agenda-ng--todo-p) (tags #'org-agenda-ng--tags-p)) - (let* ((our-lambda (when (or all any none) - (org-agenda-ng--test-lambda :all all :any any :none none))) - (pred (cond ((and our-lambda pred) - (lambda () - (and (funcall our-lambda) - (funcall pred)))) - (our-lambda our-lambda) - (pred pred) - (t (user-error "No tests given"))))) - (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (point) - while (outline-next-heading)))))) + (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (point) + while (outline-next-heading))))) ;;;; Faces/properties From fc64ec78bd73902d3fec035e2718da6fe33ef41a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:16:14 -0600 Subject: [PATCH 029/970] Make nicer --- org-agenda-ng.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e03203c..34cd7fa 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -56,10 +56,10 @@ ;;;; Commands (cl-defun org-agenda-ng--agenda (&key files pred) - (unless files - (setq files (buffer-file-name (current-buffer)))) - (unless (listp files) - (setq files (list files))) + (setq files (cl-typecase files + (null (list (buffer-file-name (current-buffer)))) + (list files) + (string (list files)))) (mapc 'find-file-noselect files) (let* ((org-use-tag-inheritance t) (entries (-flatten From 29eec8ba2594481dc0898c57bb2b600fde82cd6c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:19:43 -0600 Subject: [PATCH 030/970] More --- org-agenda-ng.el | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 34cd7fa..c875247 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -62,23 +62,10 @@ (string (list files)))) (mapc 'find-file-noselect files) (let* ((org-use-tag-inheritance t) - (entries (-flatten - (--map (with-current-buffer (find-buffer-visiting it) - ;; FIXME: It would be more optimal to - ;; gather the entry at each matching - ;; position instead of returning a list of - ;; positions and then having to go back - ;; and get the entries at each position. - (let* ((positions (org-agenda-ng--filter-buffer :pred pred)) - (elements (--map (org-with-point-at it - (org-element-headline-parser - ;; FIXME: This is a hack - (save-excursion - (forward-line 3) - (point)))) - positions))) - (mapcar #'org-agenda-ng--format-element elements))) - files))) + (entries (-flatten (--map (with-current-buffer (find-buffer-visiting it) + (mapcar #'org-agenda-ng--format-element + (org-agenda-ng--filter-buffer :pred pred))) + files))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer @@ -102,7 +89,6 @@ while (outline-next-heading))))) (cl-defun org-agenda-ng--filter-buffer (&key pred) - ;; TODO: Remove all, any, and none, and just use the predicate lambda. "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." @@ -116,7 +102,11 @@ NONE-PREDS." (when (org-before-first-heading-p) (outline-next-heading)) (cl-loop when (funcall pred) - collect (point) + collect (org-element-headline-parser + ;; FIXME: This bound is a hack + (save-excursion + (forward-line 3) + (point))) while (outline-next-heading))))) ;;;; Faces/properties From 08ee9e159649a853f0ec45dd74635381800572e2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 11:20:04 -0600 Subject: [PATCH 031/970] Prune --- org-agenda-ng.el | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c875247..b87b7ae 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -78,16 +78,6 @@ ;;;; Functions -(cl-defun org-agenda-ng--heading-positions (file) - "Return list of heading positions in FILE." - (with-current-buffer (find-buffer-visiting file) - (save-excursion - (goto-char (point-min)) - (cl-loop initially do (when (org-before-first-heading-p) - (outline-next-heading)) - collect (point) - while (outline-next-heading))))) - (cl-defun org-agenda-ng--filter-buffer (&key pred) "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all From 94e27fec8ad7b149af421220c314c0d1cf1a9e30 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 3 Jan 2018 12:21:05 -0600 Subject: [PATCH 032/970] More --- notes.org | 412 ++++++++++++++++++++++++++++++++++++++++++++--- org-agenda-ng.el | 32 +++- 2 files changed, 420 insertions(+), 24 deletions(-) diff --git a/notes.org b/notes.org index fc1d3f0..4a1cf6e 100644 --- a/notes.org +++ b/notes.org @@ -13,26 +13,31 @@ This basically works, as a very basic kind of agenda view, but we can already se ** Macro #+BEGIN_SRC elisp - (defmacro elp-profile (times &rest body) + (defmacro elp-profile (times prefixes &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)) + (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 ** ng @@ -298,3 +303,372 @@ outline-on-heading-p 3452 0.0101 string-match 4594 0.0064121759 1.395...e-06 mapcar 30 0.0041008740 0.0001366958 #+end_example + +* 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 + + +** 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 + +** 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 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 | diff --git a/org-agenda-ng.el b/org-agenda-ng.el index b87b7ae..6f8a25f 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -92,11 +92,33 @@ NONE-PREDS." (when (org-before-first-heading-p) (outline-next-heading)) (cl-loop when (funcall pred) - collect (org-element-headline-parser - ;; FIXME: This bound is a hack - (save-excursion - (forward-line 3) - (point))) + collect (let* ((next-heading (save-excursion + ;; Limit next search to up to the next heading. It + ;; would be nice to avoid doing this extra + ;; re-search-forward, but I don't see any way to avoid + ;; it. + (outline-next-heading) + (point))) + (limit (save-excursion + ;; Skip drawers and planning lines (see + ;; `org-agenda-get-some-entry-text'. I wish there were a + ;; cleaner, more canonical way to do this.) + (if (re-search-forward (rx (or (repeat 2 "\n") + (regexp ;; This is org-drawer-regexp + "^[ ]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ ]*$") + (eval (concat "^[ \t]*" org-keyword-time-regexp + ".*\n?")))) + next-heading 'noerror) + (point) + (point-max))))) + ;; NOTE: As an alternative to the two searches above, we could just move one + ;; or two lines down so that the headline parser can be sure to get the + ;; planning lines. And that does work fine in my limited testing. But then + ;; we have to keep in mind that the headline parser will never see property + ;; drawers, so if we need to search properties, we have to do that manually + ;; in predicates. So I'm going to leave it this way for now. It should + ;; probably be profiled both ways to see what the performance impact is. + (org-element-headline-parser limit)) while (outline-next-heading))))) ;;;; Faces/properties From 889a50a3d1fb5b41af9db39efe964b1e9d714a0f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:08:54 -0600 Subject: [PATCH 033/970] Add: Priority selector --- org-agenda-ng.el | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 6f8a25f..c953970 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -85,6 +85,7 @@ NONE-PREDS." (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) (date #'org-agenda-ng--date-p) (habit #'org-agenda-ng--habit-p) + (priority #'org-agenda-ng--priority-p) (todo #'org-agenda-ng--todo-p) (tags #'org-agenda-ng--tags-p)) (org-with-wide-buffer @@ -364,5 +365,42 @@ like one returned by `date-to-day'." (error "Unknown date-element type: %s" (org-element-property :type date-element))))) (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) +(defmacro org-agenda-ng--priority-p (&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." + (let* (comparator) + (cond ((null priority) + ;; No comparator given: compare only given priority with = + (setq priority comparator-or-priority + comparator '=)) + (t + ;; Both comparator and priority given + (setq comparator comparator-or-priority))) + (setq comparator (cl-case comparator + ;; Invert comparator because higher priority means lower number + (< '>) + (> '<) + (<= '>=) + (>= '<=) + (= '=) + (otherwise (user-error "Invalid comparator: %s" comparator)))) + (setq priority (* 1000 (- org-lowest-priority (string-to-char priority)))) + `(when-let ((item-priority (save-excursion + (save-match-data + ;; FIXME: Is the save-match-data above necessary? + (when (and (looking-at org-heading-regexp) + (save-match-data + (string-match org-priority-regexp (match-string 0)))) + ;; TODO: Items with no priority + ;; should not be the same as B + ;; priority. That's not very + ;; useful IMO. Better to do it + ;; like in org-super-agenda. + (org-get-priority (match-string 0))))))) + (funcall ',comparator ,priority item-priority)))) + (defun org-agenda-ng--habit-p () (org-is-habit-p)) From 9dc1fca03458dd9b77f83f5e11706b37a354fa53 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:17:31 -0600 Subject: [PATCH 034/970] Add: org-ql alias and todo --- org-agenda-ng.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c953970..23fca93 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -53,6 +53,11 @@ :pred (lambda () ,@pred-body))) +;; TODO: Return different kinds of results for org-ql? i.e. maybe it +;; shouldn't always open an agenda-like view; maybe it should return a +;; list of positions or propertized strings instead. +(defalias 'org-ql 'org-agenda-ng) + ;;;; Commands (cl-defun org-agenda-ng--agenda (&key files pred) From 5dd90e07e05396130310a93fb815dac62416f71f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:18:18 -0600 Subject: [PATCH 035/970] Change: Use outline-back-to-heading instead of org-back-to-heading Slightly faster, I think. --- org-agenda-ng.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 23fca93..c68dd96 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -92,7 +92,8 @@ NONE-PREDS." (habit #'org-agenda-ng--habit-p) (priority #'org-agenda-ng--priority-p) (todo #'org-agenda-ng--todo-p) - (tags #'org-agenda-ng--tags-p)) + (tags #'org-agenda-ng--tags-p) + (org-back-to-heading #'outline-back-to-heading)) (org-with-wide-buffer (goto-char (point-min)) (when (org-before-first-heading-p) From bdea8c923aee3a6aa24d188505a13222f54b21e7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:18:48 -0600 Subject: [PATCH 036/970] Change: Remove extra code We don't need to find the next heading, because org-element-headline-parser doesn't care. --- org-agenda-ng.el | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c68dd96..76fc0f3 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -99,33 +99,7 @@ NONE-PREDS." (when (org-before-first-heading-p) (outline-next-heading)) (cl-loop when (funcall pred) - collect (let* ((next-heading (save-excursion - ;; Limit next search to up to the next heading. It - ;; would be nice to avoid doing this extra - ;; re-search-forward, but I don't see any way to avoid - ;; it. - (outline-next-heading) - (point))) - (limit (save-excursion - ;; Skip drawers and planning lines (see - ;; `org-agenda-get-some-entry-text'. I wish there were a - ;; cleaner, more canonical way to do this.) - (if (re-search-forward (rx (or (repeat 2 "\n") - (regexp ;; This is org-drawer-regexp - "^[ ]*:\\(\\(?:\\w\\|[-_]\\)+\\):[ ]*$") - (eval (concat "^[ \t]*" org-keyword-time-regexp - ".*\n?")))) - next-heading 'noerror) - (point) - (point-max))))) - ;; NOTE: As an alternative to the two searches above, we could just move one - ;; or two lines down so that the headline parser can be sure to get the - ;; planning lines. And that does work fine in my limited testing. But then - ;; we have to keep in mind that the headline parser will never see property - ;; drawers, so if we need to search properties, we have to do that manually - ;; in predicates. So I'm going to leave it this way for now. It should - ;; probably be profiled both ways to see what the performance impact is. - (org-element-headline-parser limit)) + collect (org-element-headline-parser (line-end-position)) while (outline-next-heading))))) ;;;; Faces/properties From 949ef58c61c841ffa25f8a14ae49481cce789005 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:19:27 -0600 Subject: [PATCH 037/970] Fix: Indentation --- org-agenda-ng.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 76fc0f3..8b0f89c 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -319,13 +319,13 @@ like one returned by `date-to-day'." (:scheduled (org-entry-get (point) "SCHEDULED")) (:closed (org-entry-get (point) "CLOSED")))) (date-element (with-temp-buffer - ;; FIXME: Hack: since we're using - ;; (org-element-property :type date-element) - ;; below, we need this date parsed into an - ;; org-element element - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)))) + ;; FIXME: Hack: since we're using + ;; (org-element-property :type date-element) + ;; below, we need this date parsed into an + ;; org-element element + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)))) (pcase comparator ;; Not comparing, just checking if it has one ('nil t) From 8d096188bbc040db1a8e1a608f5e2add6fe98dd6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:21:21 -0600 Subject: [PATCH 038/970] Add notes --- notes.org | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/notes.org b/notes.org index 4a1cf6e..0792d4b 100644 --- a/notes.org +++ b/notes.org @@ -6,6 +6,37 @@ [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. +* Examples / testing + +#+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" + (or (tags "Emacs") + (priority >= "B"))) +#+END_SRC + * Profiling 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. @@ -303,7 +334,6 @@ outline-on-heading-p 3452 0.0101 string-match 4594 0.0064121759 1.395...e-06 mapcar 30 0.0041008740 0.0001366958 #+end_example - * Profiling position-based ** Macro From bc1976d96cbd2276b9bc3e8b3bb7083f58d1c29f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:22:10 -0600 Subject: [PATCH 039/970] Add todo --- org-agenda-ng.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 8b0f89c..e521096 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -304,6 +304,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (otherwise (seq-intersection tags tags-at))))) (defun org-agenda-ng--date-p (type &optional comparator target-date) + ;; TODO: Make this a macro so we don't have to quote comparator and test it for every item. "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. From eeb70b0b8e05fcf860122397cfa8d835e7a65695 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 6 Jan 2018 04:32:38 -0600 Subject: [PATCH 040/970] Add todo --- org-agenda-ng.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e521096..3d331cd 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -305,6 +305,8 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (defun org-agenda-ng--date-p (type &optional comparator target-date) ;; TODO: Make this a macro so we don't have to quote comparator and test it for every item. + + ;; TODO: Make separate date, scheduled, deadline macros. "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. From 5af85cd7d4161b4683b011f009175745d07dd9f2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 30 Jan 2018 01:42:16 -0600 Subject: [PATCH 041/970] Add notes --- notes.org | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/notes.org b/notes.org index 0792d4b..784b9d9 100644 --- a/notes.org +++ b/notes.org @@ -6,6 +6,16 @@ [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. +** Byte-compile lambdas + +=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. + +** Use macros for =date= + +If I made the =date= selector a macro, I could avoid the need to quote the comparator. + * Examples / testing #+BEGIN_SRC elisp @@ -20,6 +30,7 @@ (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))) From ad16be39bded45e7d7eaba7e43f075eecb0d9d6a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 13:26:18 -0500 Subject: [PATCH 042/970] Use org-trust-scanner-tags --- notes.org | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ org-agenda-ng.el | 12 +++++--- 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/notes.org b/notes.org index 784b9d9..ad379f3 100644 --- a/notes.org +++ b/notes.org @@ -82,6 +82,8 @@ This basically works, as a very basic kind of agenda view, but we can already se 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 @@ -464,6 +466,77 @@ org-back-to-heading 725 0.0037 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 diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 3d331cd..dc2126c 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -67,6 +67,8 @@ (string (list files)))) (mapc 'find-file-noselect files) (let* ((org-use-tag-inheritance t) + (org-scanner-tags nil) + (org-trust-scanner-tags t) (entries (-flatten (--map (with-current-buffer (find-buffer-visiting it) (mapcar #'org-agenda-ng--format-element (org-agenda-ng--filter-buffer :pred pred))) @@ -139,12 +141,12 @@ Its property list should be the second item in the list, as returned by `org-ele )) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-agenda-ng--add-todo-face it))) - (tag-list (if org-agenda-use-tag-inheritance + ;; 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 (if-let ((marker (or (org-element-property :org-hd-marker element) (org-element-property :org-marker element) (org-element-property :begin element)))) - (org-with-point-at marker - (org-get-tags-at)) + (org-get-tags-at marker (not org-use-tag-inheritance)) ;; No marker found (warn "No marker found for item: %s" title) (org-element-property :tags element)) @@ -298,7 +300,9 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." ;; TODO: Try to use `org-make-tags-matcher' to improve performance. (when-let ((tags-at (org-get-tags-at (point) ;; FIXME: Would be nice to not check this for every heading checked. - (not (member 'agenda org-agenda-use-tag-inheritance))))) + ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. + ;; (not (member 'agenda org-agenda-use-tag-inheritance)) + org-use-tag-inheritance))) (cl-typecase tags (null t) (otherwise (seq-intersection tags tags-at))))) From b2b0d068e02077b1d4670aed6ec1f2d41790cf29 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 13:26:47 -0500 Subject: [PATCH 043/970] Add stuff --- README.org | 9 ++++ notes.org | 119 +++++++++++++++++++++++++++++++++++++++++++++-- org-agenda-ng.el | 4 +- 3 files changed, 127 insertions(+), 5 deletions(-) diff --git a/README.org b/README.org index d5ada05..0a34779 100644 --- a/README.org +++ b/README.org @@ -29,4 +29,13 @@ Here are some other examples: (date :scheduled '<= (org-today)) (and (todo "DONE" "CANCELLED") (date :closed '= (org-today))))) + + (org-agenda-ng "~/org/main.org" + (or (habit) + (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))) + (and (todo "DONE" "CANCELLED") + (date :closed '= (org-today))))) #+END_SRC diff --git a/notes.org b/notes.org index ad379f3..76db775 100644 --- a/notes.org +++ b/notes.org @@ -6,15 +6,128 @@ [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. -** Byte-compile lambdas +** Use macros for =date= + +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. + +** 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. -** Use macros for =date= +*** Profiling -If I made the =date= selector a macro, I could avoid the need to quote the comparator. +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. * Examples / testing diff --git a/org-agenda-ng.el b/org-agenda-ng.el index dc2126c..1ed22ad 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -50,8 +50,8 @@ (cl-defmacro org-agenda-ng (files &rest pred-body) (declare (indent defun)) `(org-agenda-ng--agenda :files ,files - :pred (lambda () - ,@pred-body))) + :pred (byte-compile (lambda () + ,@pred-body)))) ;; TODO: Return different kinds of results for org-ql? i.e. maybe it ;; shouldn't always open an agenda-like view; maybe it should return a From 96fb97d4bd099dd758e2aeac61173d4c03dde088 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 14:01:49 -0500 Subject: [PATCH 044/970] Show relative due date (with actual date as tooltip) --- org-agenda-ng.el | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 1ed22ad..4b59fef 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -164,7 +164,10 @@ Its property list should be the second item in the list, as returned by `org-ele (habit-property (org-with-point-at (org-element-property :begin element) (when (org-is-habit-p) (org-habit-parse-todo)))) - (string (s-join " " (list todo-keyword priority-string title tag-string)))) + (due-string (pcase (org-element-property :relative-due-date element) + ('nil "") + (string (format " %s " (org-add-props string nil 'face 'underline))))) + (string (s-join " " (list todo-keyword priority-string title due-string tag-string)))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string @@ -249,11 +252,18 @@ Its property list should be the second item in the list, as returned by `org-ele element)) (defun org-agenda-ng--add-deadline-face (element) - "Add faces to ELEMENT's title for its deadline status." + "Add faces to ELEMENT's title for its deadline status. +Also store relative due date as string in `:relative-due-date' +property." (if-let ((deadline-date (org-element-property :deadline element))) (let* ((today-day-number (org-today)) (deadline-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter deadline-date 'ignore))) + (difference-days (- today-day-number deadline-day-number)) + (relative-due-date (pcase difference-days + (0 "today") + (_ (org-add-props (format "%sd ago" difference-days) nil + 'help-echo (org-element-property :raw-value deadline-date))))) (todo-keyword (org-element-property :todo-keyword element)) (done-p (member todo-keyword org-done-keywords)) (today-p (= today-day-number deadline-day-number)) @@ -266,7 +276,8 @@ Its property list should be the second item in the list, as returned by `org-ele (org-add-props it nil 'face face))) (properties (--> (second element) - (plist-put it :title title)))) + (plist-put it :title title) + (plist-put it :relative-due-date relative-due-date)))) (list (car element) properties)) ;; No deadline From 7a1e22da505ea4c182317cbff3b718527f91f394 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 14:30:29 -0500 Subject: [PATCH 045/970] Fix deadline/scheduled warning days, and improve relative date formatting --- org-agenda-ng.el | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 4b59fef..76bef8b 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -104,6 +104,16 @@ NONE-PREDS." collect (org-element-headline-parser (line-end-position)) while (outline-next-heading))))) +(defun org-agenda-ng--format-relative-date (difference) + "Return relative date string for DIFFERENCE. +DIFFERENCE should be an integer number of days, positive for +dates in the past, and negative for dates in the future." + (cond ((> difference 0) + (format "%sd ago" difference)) + ((< difference 0) + (format "in %sd" (* -1 difference))) + (t "today"))) + ;;;; Faces/properties (defun org-agenda-ng--add-markers (element) @@ -209,6 +219,11 @@ Its property list should be the second item in the list, as returned by `org-ele today-day-number) (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) + (difference-days (- today-day-number scheduled-day-number)) + (relative-due-date (pcase difference-days + (0 "today") + (_ (org-add-props (org-agenda-ng--format-relative-date difference-days) nil + 'help-echo (org-element-property :raw-value scheduled-date))))) (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) ((< today-day-number scheduled-day-number) scheduled-day-number) (t (org-time-string-to-absolute @@ -233,7 +248,8 @@ Its property list should be the second item in the list, as returned by `org-ele (org-add-props it nil 'face face))) (properties (--> (second element) - (plist-put it :title title))) + (plist-put it :title title) + (plist-put it :relative-due-date relative-due-date))) (prefix (cl-destructuring-bind (first next) org-agenda-scheduled-leaders (cond ((> scheduled-day-number today-day-number) ;; Future @@ -262,7 +278,7 @@ property." (difference-days (- today-day-number deadline-day-number)) (relative-due-date (pcase difference-days (0 "today") - (_ (org-add-props (format "%sd ago" difference-days) nil + (_ (org-add-props (org-agenda-ng--format-relative-date difference-days) nil 'help-echo (org-element-property :raw-value deadline-date))))) (todo-keyword (org-element-property :todo-keyword element)) (done-p (member todo-keyword org-done-keywords)) @@ -348,10 +364,11 @@ like one returned by `date-to-day'." ;; Not comparing, just checking if it has one ('nil t) ;; Compare dates - ((and (pred functionp) (guard target-date)) + ((pred functionp) (let ((target-day-number (cl-typecase target-date ;; Append time to target-date ;; because `date-to-day' requires it + (null (+ (org-get-wdays timestamp) (org-today))) (string (date-to-day (concat target-date " 00:00"))) (integer target-date)))) (pcase (org-element-property :type date-element) From 9147c891a19be28bf5146e0181de927acdd49f9f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 15:11:09 -0500 Subject: [PATCH 046/970] More stuff --- README.org | 36 +++++++++++++++- notes.org | 106 ++++++++++++++++++++++++++++++++++++----------- org-agenda-ng.el | 53 +++++++++++++++++------- 3 files changed, 156 insertions(+), 39 deletions(-) diff --git a/README.org b/README.org index 0a34779..58c3151 100644 --- a/README.org +++ b/README.org @@ -1,3 +1,5 @@ +* org-agenda-ng / org-ql + This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does, but it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. Here's an example of generating a kind of agenda view for today (note that the grouping is provided by [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], not this code: @@ -33,9 +35,41 @@ Here are some other examples: (org-agenda-ng "~/org/main.org" (or (habit) (and (or (date :date '= (org-today)) - (date :deadline '<= (+ org-deadline-warning-days (org-today))) + (date :deadline '<=) (date :scheduled '<= (org-today))) (not (apply #'todo org-done-keywords-for-agenda))) (and (todo "DONE" "CANCELLED") (date :closed '= (org-today))))) + + (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 + +** org-ql + +Another way to look at it is like a "query language" for Org buffers. For example: + +#+BEGIN_SRC elisp + (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 + +Instead of opening an agenda-like buffer with matching entries, =org-ql= could take a function as an argument that would be called at each matching entry to return a result, and finally it would return a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. diff --git a/notes.org b/notes.org index 76db775..65209e9 100644 --- a/notes.org +++ b/notes.org @@ -2,11 +2,21 @@ * Ideas -** Operate on list of heading positions +** 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. -** Use macros for =date= +[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. @@ -157,15 +167,24 @@ Doesn't seem to make any difference. (tags "Emacs") (priority >= "B"))) (org-ql "~/org/main.org" - (or (tags "Emacs") - (priority >= "B"))) + (and (or (tags "Emacs") + (priority >= "B")) + (not (done)))) + (org-ql "~/org/main.org" + (and (or (tags "Emacs") + (priority >= "B")) + (done))) #+END_SRC * Profiling +** 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. -** Macro +[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) @@ -197,7 +216,7 @@ This basically works, as a very basic kind of agenda view, but we can already se [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 +*** ng #+BEGIN_SRC elisp (elp-profile 1 (org-agenda-ng--test-agenda-today)) @@ -227,7 +246,7 @@ outline-back-to-heading 6897 0.3587 line-beginning-position 11702 0.2887473860 2.467...e-05 #+end_example -** orig +*** orig Make sure to kill any existing agenda buffers first. @@ -430,7 +449,7 @@ org-agenda-use-sticky-p 1 4.73e- mapatoms 1 0 0.0 #+end_example -** Profile org-element-map +*** Profile org-element-map #+BEGIN_SRC elisp (elp-profile 1 (with-current-buffer (find-buffer-visiting "~/org/main.org") @@ -460,9 +479,9 @@ outline-on-heading-p 3452 0.0101 string-match 4594 0.0064121759 1.395...e-06 mapcar 30 0.0041008740 0.0001366958 #+end_example -* Profiling position-based +** Profiling position-based -** Macro +*** Macro #+BEGIN_SRC elisp (defmacro elp-profile (times &rest body) @@ -488,7 +507,7 @@ mapcar 30 0.0041 #+END_SRC -** orig +*** orig Make sure to kill any existing agenda buffers first. @@ -520,7 +539,7 @@ org-agenda-format-item 279 0.7552 re-search-backward 16726 0.5694224969 3.404...e-05 #+end_example -** ng-funcall +*** ng-funcall #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--test-agenda-today)) @@ -550,7 +569,7 @@ org-parse-time-string 300 0.0032 org-agenda-ng--add-scheduled-face 75 0.0031410580 4.188...e-05 #+end_example -** ng-flet +*** ng-flet #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--test-agenda-today)) @@ -579,7 +598,7 @@ org-back-to-heading 725 0.0037 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= +** Profiling =org-trust-scanner-tags= [2018-05-10 Thu 12:59] Turned on =org-trust-scanner-tags=, going to try profiling again: @@ -651,9 +670,9 @@ Now trying again without it: Wow, using =org-trust-scanner-tags= saves a /lot/ of time. -* Profiling flet across all agenda files +** Profiling flet across all agenda files -** Without flet +*** Without flet #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--agenda @@ -690,7 +709,7 @@ org-time-string-to-absolute 3780 0.8277 #+end_example -** With flet +*** With flet #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--agenda @@ -726,11 +745,11 @@ org-parse-time-string 7560 1.7121 org-element--get-time-properties 1180 1.1814058020 0.0010011913 #+end_example -* Profiling flet on a single file +** 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 +*** Without flet #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--agenda @@ -767,7 +786,7 @@ org-super-agenda--filter-finalize-entries 5 0.1324 #+end_example -** With flet +*** With flet #+BEGIN_SRC elisp (elp-profile 5 (org-agenda-ng--agenda @@ -803,9 +822,9 @@ org-agenda-finalize-entries 5 0.1607 org-super-agenda--filter-finalize-entries 5 0.1316961509 0.0263392301 #+end_example -* Profiling tags matching +** Profiling tags matching -** ng +*** ng #+BEGIN_SRC elisp (elp-profile 1 nil (org-agenda-ng "~/org/main.org" @@ -836,7 +855,7 @@ org-super-agenda--filter-finalize-entries 5 0.1316 | buffer-substring-no-properties | 6329 | 0.0308716979 | 4.877...e-06 | | line-end-position | 903 | 0.0280484950 | 3.106...e-05 | -** ng without inheritance +*** ng without inheritance #+BEGIN_SRC elisp (elp-profile 1 nil (org-agenda-ng "~/org/main.org" @@ -868,7 +887,7 @@ org-super-agenda--filter-finalize-entries 5 0.1316 | buffer-substring-no-properties | 6329 | 0.0285818689 | 4.516...e-06 | -** original +*** original #+BEGIN_SRC elisp (elp-profile 1 nil @@ -899,3 +918,42 @@ org-super-agenda--filter-finalize-entries 5 0.1316 | 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 | diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 76bef8b..079ab85 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -89,20 +89,26 @@ "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." - (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) - (date #'org-agenda-ng--date-p) - (habit #'org-agenda-ng--habit-p) - (priority #'org-agenda-ng--priority-p) - (todo #'org-agenda-ng--todo-p) - (tags #'org-agenda-ng--tags-p) - (org-back-to-heading #'outline-back-to-heading)) - (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (org-element-headline-parser (line-end-position)) - while (outline-next-heading))))) + ;; Cache `org-today' so we don't have to run it repeatedly. + (cl-flet ((org-today nil `(progn ,(org-today)))) + (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) + (date #'org-agenda-ng--date-plain-p) + (deadline #'org-agenda-ng--deadline-p) + (scheduled #'org-agenda-ng--scheduled-p) + (closed #'org-agenda-ng--closed-p) + (habit #'org-agenda-ng--habit-p) + (priority #'org-agenda-ng--priority-p) + (todo #'org-agenda-ng--todo-p) + (done #'org-agenda-ng--done-p) + (tags #'org-agenda-ng--tags-p) + (org-back-to-heading #'outline-back-to-heading)) + (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (org-element-headline-parser (line-end-position)) + while (outline-next-heading)))))) (defun org-agenda-ng--format-relative-date (difference) "Return relative date string for DIFFERENCE. @@ -322,6 +328,9 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (symbol (member state (symbol-value keywords))) (otherwise (user-error "Invalid todo keywords: %s" keywords))))) +(defsubst org-agenda-ng--done-p () + (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)) + (defun org-agenda-ng--tags-p (&rest tags) "Return non-nil if current heading has TAGS." ;; TODO: Try to use `org-make-tags-matcher' to improve performance. @@ -380,6 +389,22 @@ like one returned by `date-to-day'." (error "Unknown date-element type: %s" (org-element-property :type date-element))))) (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) +(defsubst org-agenda-ng--date-plain-p (&optional comparator target-date) + (org-agenda-ng--date-p :date comparator target-date)) +(defsubst org-agenda-ng--deadline-p (&optional comparator target-date) + ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries + ;; that have any deadline. But the common case of wanting to select entries whose deadline is + ;; within the warning days (either the global setting or that entry's setting) requires the user + ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that + ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of + ;; course, that would make the deadline selector different from the scheduled, closed, and date + ;; selectors, which would also be unintuitive. + (org-agenda-ng--date-p :deadline comparator target-date)) +(defsubst org-agenda-ng--scheduled-p (&optional comparator target-date) + (org-agenda-ng--date-p :scheduled comparator target-date)) +(defsubst org-agenda-ng--closed-p (&optional comparator target-date) + (org-agenda-ng--date-p :closed comparator target-date)) + (defmacro org-agenda-ng--priority-p (&optional comparator-or-priority priority) "Return non-nil if current heading has a certain priority. COMPARATOR-OR-PRIORITY should be either a comparator function, From 146772af67b66273eac1d6b2fb2922df11eab34b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 15:38:44 -0500 Subject: [PATCH 047/970] And more --- README.org | 23 ++++++++++++++++------- org-agenda-ng.el | 43 +++++++++++++++++++++++++++++-------------- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/README.org b/README.org index 58c3151..20fb7bf 100644 --- a/README.org +++ b/README.org @@ -9,7 +9,7 @@ Here's an example of generating a kind of agenda view for today (note that the g (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)))) + (not (done)))) #+END_SRC [[screenshot.png]] @@ -37,7 +37,7 @@ Here are some other examples: (and (or (date :date '= (org-today)) (date :deadline '<=) (date :scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))) + (not (done))) (and (todo "DONE" "CANCELLED") (date :closed '= (org-today))))) @@ -46,7 +46,7 @@ Here are some other examples: (and (or (date '= (org-today)) (deadline '<=) (scheduled '<= (org-today))) - (not (apply #'todo org-done-keywords-for-agenda))) + (not (done))) (and (todo "DONE" "CANCELLED") (closed '= (org-today))))) #+END_SRC @@ -59,17 +59,26 @@ Another way to look at it is like a "query language" for Org buffers. For examp (org-ql org-agenda-files (and (todo "SOMEDAY") (tags "Emacs") - (priority >= "B"))) + (priority >= "B"))) ;; => ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) (org-ql "~/org/main.org" (and (or (tags "Emacs") (priority >= "B")) - (not (done)))) + (not (done)))) ;; => (((headline (:raw-value "Now" :begin 3832 :end 3843 ...))) ...) (org-ql "~/org/main.org" (and (or (tags "Emacs") (priority >= "B")) - (done))) + (done)) + :action-fn (lambda (element) + (org-element-property :begin element))) ;; => (44154 46469 56008 63965 100008 ...) + + (mapcar (lambda (element) + (org-element-property :begin element)) + (org-ql "~/org/main.org" + (and (or (tags "Emacs") + (priority >= "B")) + (done)))) ;; => (44154 46469 56008 63965 100008 ...) #+END_SRC -Instead of opening an agenda-like buffer with matching entries, =org-ql= could take a function as an argument that would be called at each matching entry to return a result, and finally it would return a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. +Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 079ab85..50743e6 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -47,20 +47,32 @@ (symbol-function ,target))) ,@body)) -(cl-defmacro org-agenda-ng (files &rest pred-body) +(cl-defmacro org-agenda-ng (files pred-body) + "Display an agenda-like buffer of entries in FILES that match PRED-BODY." (declare (indent defun)) - `(org-agenda-ng--agenda :files ,files - :pred (byte-compile (lambda () - ,@pred-body)))) + `(org-agenda-ng--agenda ,files + (byte-compile (lambda () + ,pred-body)) + #'org-agenda-ng--format-element)) + +(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element)))) + "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. + +ACTION-FN should take a single argument, which will be the result +of calling `org-element-headline-parser' at each matching entry." + (declare (indent defun)) + `(org-ql--query ,files + (byte-compile (lambda () + ,pred-body)) + #',action-fn)) -;; TODO: Return different kinds of results for org-ql? i.e. maybe it -;; shouldn't always open an agenda-like view; maybe it should return a -;; list of positions or propertized strings instead. -(defalias 'org-ql 'org-agenda-ng) ;;;; Commands -(cl-defun org-agenda-ng--agenda (&key files pred) +;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the +;; headline-parser when they don't need it. + +(cl-defun org-ql--query (files pred action-fn) (setq files (cl-typecase files (null (list (buffer-file-name (current-buffer)))) (list files) @@ -68,11 +80,14 @@ (mapc 'find-file-noselect files) (let* ((org-use-tag-inheritance t) (org-scanner-tags nil) - (org-trust-scanner-tags t) - (entries (-flatten (--map (with-current-buffer (find-buffer-visiting it) - (mapcar #'org-agenda-ng--format-element - (org-agenda-ng--filter-buffer :pred pred))) - files))) + (org-trust-scanner-tags t)) + (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) + (mapcar action-fn + (org-agenda-ng--filter-buffer :pred pred))) + files)))) + +(cl-defun org-agenda-ng--agenda (files pred action-fn) + (let* ((entries (org-ql--query files pred action-fn)) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer From 1d9a2cfc5313ac8a1c1be2867e7fc779d05d1267 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 15:50:13 -0500 Subject: [PATCH 048/970] More... --- README.org | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.org b/README.org index 20fb7bf..c0279fc 100644 --- a/README.org +++ b/README.org @@ -6,9 +6,9 @@ Here's an example of generating a kind of agenda view for today (note that the g #+BEGIN_SRC elisp (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))) + (and (or (date '= (org-today)) + (deadline '<=) + (scheduled '<= (org-today))) (not (done)))) #+END_SRC @@ -27,19 +27,19 @@ Here are some other examples: (org-agenda-ng "~/org/main.org" (or (habit) - (date :deadline '<= (org-today)) - (date :scheduled '<= (org-today)) + (deadline '<=) + (scheduled '<= (org-today)) (and (todo "DONE" "CANCELLED") - (date :closed '= (org-today))))) + (closed '= (org-today))))) (org-agenda-ng "~/org/main.org" (or (habit) - (and (or (date :date '= (org-today)) - (date :deadline '<=) - (date :scheduled '<= (org-today))) + (and (or (date '= (org-today)) + (deadline '<=) + (scheduled '<= (org-today))) (not (done))) (and (todo "DONE" "CANCELLED") - (date :closed '= (org-today))))) + (closed '= (org-today))))) (org-agenda-ng "~/org/main.org" (or (habit) From 41b1e0e8378d267f21ac78664dcf071ba965d82a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 15:56:53 -0500 Subject: [PATCH 049/970] Simplify org-today --- README.org | 28 ++++++++++++++++++---------- org-agenda-ng.el | 7 +++++-- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/README.org b/README.org index c0279fc..2881ede 100644 --- a/README.org +++ b/README.org @@ -6,9 +6,9 @@ Here's an example of generating a kind of agenda view for today (note that the g #+BEGIN_SRC elisp (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date '= (org-today)) + (and (or (date '= today) (deadline '<=) - (scheduled '<= (org-today))) + (scheduled '<= today)) (not (done)))) #+END_SRC @@ -28,27 +28,35 @@ Here are some other examples: (org-agenda-ng "~/org/main.org" (or (habit) (deadline '<=) - (scheduled '<= (org-today)) + (scheduled '<= today) (and (todo "DONE" "CANCELLED") - (closed '= (org-today))))) + (closed '= today)))) (org-agenda-ng "~/org/main.org" (or (habit) - (and (or (date '= (org-today)) + (and (or (date '= today) (deadline '<=) - (scheduled '<= (org-today))) + (scheduled '<= today)) (not (done))) (and (todo "DONE" "CANCELLED") - (closed '= (org-today))))) + (closed '= today)))) (org-agenda-ng "~/org/main.org" (or (habit) - (and (or (date '= (org-today)) + (and (or (date '= today) (deadline '<=) - (scheduled '<= (org-today))) + (scheduled '<= today)) (not (done))) (and (todo "DONE" "CANCELLED") - (closed '= (org-today))))) + (closed '= today)))) + (org-agenda-ng "~/org/main.org" + (or (habit) + (and (or (date '= today) + (deadline '<=) + (scheduled '<= today)) + (not (done))) + (and (todo "DONE" "CANCELLED") + (closed '= today)))) #+END_SRC ** org-ql diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 50743e6..745d7a9 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -72,6 +72,8 @@ of calling `org-element-headline-parser' at each matching entry." ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. +(defvar org-ql--today nil) + (cl-defun org-ql--query (files pred action-fn) (setq files (cl-typecase files (null (list (buffer-file-name (current-buffer)))) @@ -80,7 +82,8 @@ of calling `org-element-headline-parser' at each matching entry." (mapc 'find-file-noselect files) (let* ((org-use-tag-inheritance t) (org-scanner-tags nil) - (org-trust-scanner-tags t)) + (org-trust-scanner-tags t) + (org-ql--today (org-today))) (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) (mapcar action-fn (org-agenda-ng--filter-buffer :pred pred))) @@ -105,7 +108,7 @@ of calling `org-element-headline-parser' at each matching entry." Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS." ;; Cache `org-today' so we don't have to run it repeatedly. - (cl-flet ((org-today nil `(progn ,(org-today)))) + (cl-letf ((today org-ql--today)) (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) (date #'org-agenda-ng--date-plain-p) (deadline #'org-agenda-ng--deadline-p) From 2aa3ba008ecf735088dd3594879cc813d8daf5cd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 16:14:20 -0500 Subject: [PATCH 050/970] Remove need to quote date comparators --- README.org | 37 ++++++++++--------------------------- org-agenda-ng.el | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/README.org b/README.org index 2881ede..a2edf00 100644 --- a/README.org +++ b/README.org @@ -6,9 +6,9 @@ Here's an example of generating a kind of agenda view for today (note that the g #+BEGIN_SRC elisp (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date '= today) - (deadline '<=) - (scheduled '<= today)) + (and (or (date = today) + (deadline <=) + (scheduled <= today)) (not (done)))) #+END_SRC @@ -27,36 +27,19 @@ Here are some other examples: (org-agenda-ng "~/org/main.org" (or (habit) - (deadline '<=) - (scheduled '<= today) + (deadline <=) + (scheduled <= today) (and (todo "DONE" "CANCELLED") - (closed '= today)))) + (closed = today)))) (org-agenda-ng "~/org/main.org" (or (habit) - (and (or (date '= today) - (deadline '<=) - (scheduled '<= today)) + (and (or (date = today) + (deadline <=) + (scheduled <= today)) (not (done))) (and (todo "DONE" "CANCELLED") - (closed '= today)))) - - (org-agenda-ng "~/org/main.org" - (or (habit) - (and (or (date '= today) - (deadline '<=) - (scheduled '<= today)) - (not (done))) - (and (todo "DONE" "CANCELLED") - (closed '= today)))) - (org-agenda-ng "~/org/main.org" - (or (habit) - (and (or (date '= today) - (deadline '<=) - (scheduled '<= today)) - (not (done))) - (and (todo "DONE" "CANCELLED") - (closed '= today)))) + (closed = today)))) #+END_SRC ** org-ql diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 745d7a9..49ea752 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -47,12 +47,19 @@ (symbol-function ,target))) ,@body)) +;; FIXME: DRY these two macros. + (cl-defmacro org-agenda-ng (files pred-body) "Display an agenda-like buffer of entries in FILES that match PRED-BODY." (declare (indent defun)) `(org-agenda-ng--agenda ,files (byte-compile (lambda () - ,pred-body)) + (cl-symbol-macrolet ((= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body))) #'org-agenda-ng--format-element)) (cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element)))) @@ -63,7 +70,12 @@ of calling `org-element-headline-parser' at each matching entry." (declare (indent defun)) `(org-ql--query ,files (byte-compile (lambda () - ,pred-body)) + (cl-symbol-macrolet ((= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body))) #',action-fn)) From 89ae2ecf4a42b8b7256a41c7e3317b440157b545 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 16:46:06 -0500 Subject: [PATCH 051/970] Update commentary We aren't using org-element-parse-buffer anymore. --- org-agenda-ng.el | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 49ea752..2101d12 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -7,28 +7,25 @@ ;; written in a more functional way, to avoid making multiple passes ;; through each file when building a multi-day agenda. -;; Unfortunately, however, it's more like a proof-of-nope, because -;; it's significantly slower than the existing agenda code. Profiling -;; shows that =org-element-parse-buffer= is just not a fast function, -;; so most of the time spent is in that function, parsing the whole -;; buffer into a lisp tree. The existing agenda code is not written -;; in a functional style, and it makes multiple passes through each -;; file when preparing a multi-day agenda view, but it avoids parsing -;; the /entire/ buffer the way =org-element-parse-buffer= does. - -;; So I guess this approach won't work, unless someone can come up -;; with a version of =org-element-parse-buffer= that's about 10x -;; faster. +;; It also functions as a kind of "query language" for Org buffers. ;;;; Principles -;;;;; Work on elements +;;;;; Try to imitate traditional Org agenda code's results and methods -;; We want to work on elements as returned by =org-element-parse-buffer=. We only convert to strings at the very end, when we send the list of those to =org-agenda-finalize-entries=. +;; The traditional agenda code is complicated, but well-optimized. We should imitate it where +;; possible. We should also attempt to return the same results as the traditional agenda code +;; (ultimately, that is; but whether we reach that level of complexity depends on, e.g. performance +;; achieved, whether it looks like a feasible alternative, etc). At the least, we should return +;; results in the same format, so they can be used by other code that uses agenda output +;; (e.g. org-agenda-finalize-entries, org-agenda-finalize, org-super-agenda, etc). Of course, this +;; goal does not necessarily apply to the "query language"-like features, and ideally the +;; agenda-like features should build upon those. ;;;;; Preserve the call to =org-agenda-finalize-entries= -;; We want to preserve the final call to =org-agenda-finalize-entries= to preserve compatibility with other packages and functions. +;; We want to preserve the final call to org-agenda-finalize-entries to preserve compatibility +;; with other packages and functions. ;;; Code: From 28144f84137832de32e7b180247dbe3237295429 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 16:52:26 -0500 Subject: [PATCH 052/970] Update screenshot --- screenshot.png | Bin 48041 -> 54446 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshot.png b/screenshot.png index 9a1b7c86a0fb494158bb23991b33006dd70f8066..664f891bc03649e16f24e383c385f2a5ff3aee82 100644 GIT binary patch literal 54446 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 B5n%uT literal 48041 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 Date: Thu, 10 May 2018 16:56:35 -0500 Subject: [PATCH 053/970] Update examples --- README.org | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/README.org b/README.org index a2edf00..50ab9ea 100644 --- a/README.org +++ b/README.org @@ -17,29 +17,25 @@ Here's an example of generating a kind of agenda view for today (note that the g Here are some other examples: #+BEGIN_SRC elisp + ;; Show an agenda-like view of items in all agenda files with TODO and SOMEDAY keywords which are + ;; tagged "computer" or "Emacs" and in the category "main": (org-agenda-ng org-agenda-files (and (todo "TODO" "SOMEDAY") (tags "computer" "Emacs") (category "main"))) + ;; Show an agenda-like view of all habits: (org-agenda-ng org-agenda-files (habit)) + ;; Show an agenda-like view similar to a "traditional" Org agenda: (org-agenda-ng "~/org/main.org" (or (habit) + (date = today) (deadline <=) (scheduled <= today) (and (todo "DONE" "CANCELLED") (closed = today)))) - - (org-agenda-ng "~/org/main.org" - (or (habit) - (and (or (date = today) - (deadline <=) - (scheduled <= today)) - (not (done))) - (and (todo "DONE" "CANCELLED") - (closed = today)))) #+END_SRC ** org-ql @@ -47,29 +43,29 @@ Here are some other examples: Another way to look at it is like a "query language" for Org buffers. For example: #+BEGIN_SRC elisp - (org-ql org-agenda-files + ;; Return a list of Org entry elements which have the SOMEDAY keyword, are tagged "Emacs", and have + ;; priority B or higher: + (org-ql "~/org/main.org" (and (todo "SOMEDAY") (tags "Emacs") (priority >= "B"))) ;; => ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) - (org-ql "~/org/main.org" - (and (or (tags "Emacs") - (priority >= "B")) - (not (done)))) ;; => (((headline (:raw-value "Now" :begin 3832 :end 3843 ...))) ...) - - (org-ql "~/org/main.org" - (and (or (tags "Emacs") - (priority >= "B")) - (done)) + ;; Find non-done TODO items which are tagged "Emacs" and have priority "B" or higher, and return a + ;; list of heading positions: + (org-ql org-agenda-files + (and (not (done)) + (tags "Emacs") + (priority >= "B")) :action-fn (lambda (element) (org-element-property :begin element))) ;; => (44154 46469 56008 63965 100008 ...) + ;; Or you can use mapcar around it to get the same result (API is WIP): (mapcar (lambda (element) (org-element-property :begin element)) - (org-ql "~/org/main.org" - (and (or (tags "Emacs") - (priority >= "B")) - (done)))) ;; => (44154 46469 56008 63965 100008 ...) + (org-ql org-agenda-files + (and (not (done)) + (tags "Emacs") + (priority >= "B")))) ;; => (44154 46469 56008 63965 100008 ...) #+END_SRC Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. From 96dd06b14498b8ac61948c92a3f2adc52855f34d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 17:00:17 -0500 Subject: [PATCH 054/970] Few changes --- notes.org | 11 +++++++++++ org-agenda-ng.el | 17 +++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/notes.org b/notes.org index 65209e9..c3979bd 100644 --- a/notes.org +++ b/notes.org @@ -176,6 +176,17 @@ Doesn't seem to make any difference. (done))) #+END_SRC +** Screenshot code + +#+BEGIN_SRC elisp + (org-super-agenda--test-with-org-today-date "2017-07-08 00:00" + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (and (or (date = today) + (deadline <=) + (scheduled <= today)) + (not (done))))) +#+END_SRC + * Profiling ** Using =org-element-parse-buffer= diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 2101d12..e321801 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -253,10 +253,8 @@ Its property list should be the second item in the list, as returned by `org-ele (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) (difference-days (- today-day-number scheduled-day-number)) - (relative-due-date (pcase difference-days - (0 "today") - (_ (org-add-props (org-agenda-ng--format-relative-date difference-days) nil - 'help-echo (org-element-property :raw-value scheduled-date))))) + (relative-due-date (org-add-props (org-agenda-ng--format-relative-date difference-days) nil + 'help-echo (org-element-property :raw-value scheduled-date))) (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) ((< today-day-number scheduled-day-number) scheduled-day-number) (t (org-time-string-to-absolute @@ -309,10 +307,8 @@ property." (deadline-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter deadline-date 'ignore))) (difference-days (- today-day-number deadline-day-number)) - (relative-due-date (pcase difference-days - (0 "today") - (_ (org-add-props (org-agenda-ng--format-relative-date difference-days) nil - 'help-echo (org-element-property :raw-value deadline-date))))) + (relative-due-date (org-add-props (org-agenda-ng--format-relative-date difference-days) nil + 'help-echo (org-element-property :raw-value deadline-date))) (todo-keyword (org-element-property :todo-keyword element)) (done-p (member todo-keyword org-done-keywords)) (today-p (= today-day-number deadline-day-number)) @@ -371,9 +367,6 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (otherwise (seq-intersection tags tags-at))))) (defun org-agenda-ng--date-p (type &optional comparator target-date) - ;; TODO: Make this a macro so we don't have to quote comparator and test it for every item. - - ;; TODO: Make separate date, scheduled, deadline macros. "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. @@ -402,9 +395,9 @@ like one returned by `date-to-day'." ;; Compare dates ((pred functionp) (let ((target-day-number (cl-typecase target-date + (null (+ (org-get-wdays timestamp) (org-today))) ;; Append time to target-date ;; because `date-to-day' requires it - (null (+ (org-get-wdays timestamp) (org-today))) (string (date-to-day (concat target-date " 00:00"))) (integer target-date)))) (pcase (org-element-property :type date-element) From 58b2cca65f755aec6ad707b111bc3c9d3949892a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 18:43:03 -0500 Subject: [PATCH 055/970] Add regexp matcher --- README.org | 6 +++--- notes.org | 10 ++++++++++ org-agenda-ng.el | 10 ++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index 50ab9ea..a1384fd 100644 --- a/README.org +++ b/README.org @@ -50,11 +50,11 @@ Another way to look at it is like a "query language" for Org buffers. For examp (tags "Emacs") (priority >= "B"))) ;; => ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) - ;; Find non-done TODO items which are tagged "Emacs" and have priority "B" or higher, and return a - ;; list of heading positions: + ;; Find non-done items which contain the term "Emacs" and have priority "B" or higher, and + ;; return a list of heading positions: (org-ql org-agenda-files (and (not (done)) - (tags "Emacs") + (regexp "Emacs") (priority >= "B")) :action-fn (lambda (element) (org-element-property :begin element))) ;; => (44154 46469 56008 63965 100008 ...) diff --git a/notes.org b/notes.org index c3979bd..5cfefb4 100644 --- a/notes.org +++ b/notes.org @@ -176,6 +176,16 @@ Doesn't seem to make any difference. (done))) #+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 diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e321801..54ec866 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -128,6 +128,7 @@ NONE-PREDS." (todo #'org-agenda-ng--todo-p) (done #'org-agenda-ng--done-p) (tags #'org-agenda-ng--tags-p) + (regexp #'org-ql--regexp-p) (org-back-to-heading #'outline-back-to-heading)) (org-with-wide-buffer (goto-char (point-min)) @@ -464,3 +465,12 @@ comparator, PRIORITY should be a priority string." (defun org-agenda-ng--habit-p () (org-is-habit-p)) + +(defun org-ql--regexp-p (regexp) + "Return non-nil if current entry matches REGEXP." + (let ((end (or (save-excursion + (outline-next-heading)) + (point-max)))) + (save-excursion + (goto-char (line-beginning-position)) + (re-search-forward regexp end t)))) From 39a8c36b92a8036562cb170ea0b8be7ba1d2de50 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 10 May 2018 18:58:21 -0500 Subject: [PATCH 056/970] Add property matcher --- README.org | 7 +++++++ notes.org | 10 ++++++++++ org-agenda-ng.el | 13 +++++++++++++ 3 files changed, 30 insertions(+) diff --git a/README.org b/README.org index a1384fd..0fc298e 100644 --- a/README.org +++ b/README.org @@ -66,6 +66,13 @@ Another way to look at it is like a "query language" for Org buffers. For examp (and (not (done)) (tags "Emacs") (priority >= "B")))) ;; => (44154 46469 56008 63965 100008 ...) + + ;; If you kept a database of music in an Org file, you might run a query like this to find tracks + ;; composed by Chopin that do not have their key recorded in the database: + (org-ql "~/org/music.org" + (and (property "genre" "classical") + (property "composer" "Chopin") + (not (property "key")))) #+END_SRC Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. diff --git a/notes.org b/notes.org index 5cfefb4..018ae07 100644 --- a/notes.org +++ b/notes.org @@ -186,6 +186,16 @@ Doesn't seem to make any difference. (regexp "over")) #+END_SRC +** Property matching + +#+BEGIN_SRC elisp + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (property "agenda-group")) + + (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (property "agenda-group" "plans")) +#+END_SRC + ** Screenshot code #+BEGIN_SRC elisp diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 54ec866..efd6054 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -128,6 +128,7 @@ NONE-PREDS." (todo #'org-agenda-ng--todo-p) (done #'org-agenda-ng--done-p) (tags #'org-agenda-ng--tags-p) + (property #'org-ql--property-p) (regexp #'org-ql--regexp-p) (org-back-to-heading #'outline-back-to-heading)) (org-with-wide-buffer @@ -474,3 +475,15 @@ comparator, PRIORITY should be a priority string." (save-excursion (goto-char (line-beginning-position)) (re-search-forward regexp end t)))) + +(defun org-ql--property-p (property &optional value) + "Return non-nil if current entry has PROPERTY, and optionally VALUE." + (pcase property + ('nil (user-error "Property matcher requires a PROPERTY argument.")) + (_ (pcase value + ('nil + ;; Check that PROPERTY exists + (org-entry-get (point) property)) + (_ + ;; Check that PROPERTY has VALUE + (string-equal value (org-entry-get (point) property 'selective))))))) From 9050b756ba1f9fedd7552b9e3a97739e4602ad14 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 11 May 2018 16:33:34 -0500 Subject: [PATCH 057/970] Factor out org-ql into separate file --- org-agenda-ng.el | 228 +-------------------------------------------- org-ql.el | 238 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 241 insertions(+), 225 deletions(-) create mode 100644 org-ql.el diff --git a/org-agenda-ng.el b/org-agenda-ng.el index efd6054..e6ab117 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -35,14 +35,9 @@ (require 'cl-lib) (require 'seq) -;;;; Macros +(require 'org-ql) -(defmacro org-agenda-ng--fmap (fns &rest body) - (declare (indent defun)) - `(cl-letf ,(cl-loop for (fn target) in fns - collect `((symbol-function ',fn) - (symbol-function ,target))) - ,@body)) +;;;; Macros ;; FIXME: DRY these two macros. @@ -59,45 +54,11 @@ ,pred-body))) #'org-agenda-ng--format-element)) -(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element)))) - "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. - -ACTION-FN should take a single argument, which will be the result -of calling `org-element-headline-parser' at each matching entry." - (declare (indent defun)) - `(org-ql--query ,files - (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,pred-body))) - #',action-fn)) - - -;;;; Commands +;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(defvar org-ql--today nil) - -(cl-defun org-ql--query (files pred action-fn) - (setq files (cl-typecase files - (null (list (buffer-file-name (current-buffer)))) - (list files) - (string (list files)))) - (mapc 'find-file-noselect files) - (let* ((org-use-tag-inheritance t) - (org-scanner-tags nil) - (org-trust-scanner-tags t) - (org-ql--today (org-today))) - (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) - (mapcar action-fn - (org-agenda-ng--filter-buffer :pred pred))) - files)))) - (cl-defun org-agenda-ng--agenda (files pred action-fn) (let* ((entries (org-ql--query files pred action-fn)) (result-string (org-agenda-finalize-entries entries 'agenda)) @@ -110,35 +71,6 @@ of calling `org-element-headline-parser' at each matching entry." (pop-to-buffer (current-buffer)) (org-agenda-finalize)))) -;;;; Functions - -(cl-defun org-agenda-ng--filter-buffer (&key pred) - "Return positions of matching headings in current buffer. -Headings should return non-nil for any ANY-PREDS and nil for all -NONE-PREDS." - ;; Cache `org-today' so we don't have to run it repeatedly. - (cl-letf ((today org-ql--today)) - (org-agenda-ng--fmap ((category #'org-agenda-ng--category-p) - (date #'org-agenda-ng--date-plain-p) - (deadline #'org-agenda-ng--deadline-p) - (scheduled #'org-agenda-ng--scheduled-p) - (closed #'org-agenda-ng--closed-p) - (habit #'org-agenda-ng--habit-p) - (priority #'org-agenda-ng--priority-p) - (todo #'org-agenda-ng--todo-p) - (done #'org-agenda-ng--done-p) - (tags #'org-agenda-ng--tags-p) - (property #'org-ql--property-p) - (regexp #'org-ql--regexp-p) - (org-back-to-heading #'outline-back-to-heading)) - (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (org-element-headline-parser (line-end-position)) - while (outline-next-heading)))))) - (defun org-agenda-ng--format-relative-date (difference) "Return relative date string for DIFFERENCE. DIFFERENCE should be an integer number of days, positive for @@ -333,157 +265,3 @@ property." (defun org-agenda-ng--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) - -;;;; Predicates - -(defun org-agenda-ng--category-p (&rest categories) - "Return non-nil if current heading is in one or more of CATEGORIES." - (when-let ((category (org-get-category (point)))) - (cl-typecase categories - (null t) - (otherwise (member category categories))))) - -(defun org-agenda-ng--todo-p (&rest keywords) - "Return non-nil if current heading is a TODO item. -With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." - (when-let ((state (org-get-todo-state))) - (cl-typecase keywords - (null t) - (list (member state keywords)) - (symbol (member state (symbol-value keywords))) - (otherwise (user-error "Invalid todo keywords: %s" keywords))))) - -(defsubst org-agenda-ng--done-p () - (apply #'org-agenda-ng--todo-p org-done-keywords-for-agenda)) - -(defun org-agenda-ng--tags-p (&rest tags) - "Return non-nil if current heading has TAGS." - ;; TODO: Try to use `org-make-tags-matcher' to improve performance. - (when-let ((tags-at (org-get-tags-at (point) - ;; FIXME: Would be nice to not check this for every heading checked. - ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. - ;; (not (member 'agenda org-agenda-use-tag-inheritance)) - org-use-tag-inheritance))) - (cl-typecase tags - (null t) - (otherwise (seq-intersection tags tags-at))))) - -(defun org-agenda-ng--date-p (type &optional comparator target-date) - "Return non-nil if current heading has a date property of TYPE. -TYPE should be a keyword symbol, like :scheduled or :deadline. - -With COMPARATOR and TARGET-DATE, return non-nil if entry's -scheduled date compares with TARGET-DATE according to COMPARATOR. -TARGET-DATE may be a string like \"2017-08-05\", or an integer -like one returned by `date-to-day'." - (when-let ((timestamp (pcase type - ;; FIXME: Add :date selector, since I put it - ;; in the examples but forgot to actually - ;; make it. - (:deadline (org-entry-get (point) "DEADLINE")) - (:scheduled (org-entry-get (point) "SCHEDULED")) - (:closed (org-entry-get (point) "CLOSED")))) - (date-element (with-temp-buffer - ;; FIXME: Hack: since we're using - ;; (org-element-property :type date-element) - ;; below, we need this date parsed into an - ;; org-element element - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)))) - (pcase comparator - ;; Not comparing, just checking if it has one - ('nil t) - ;; Compare dates - ((pred functionp) - (let ((target-day-number (cl-typecase target-date - (null (+ (org-get-wdays timestamp) (org-today))) - ;; Append time to target-date - ;; because `date-to-day' requires it - (string (date-to-day (concat target-date " 00:00"))) - (integer target-date)))) - (pcase (org-element-property :type date-element) - ((or 'active 'inactive) - (funcall comparator - (org-time-string-to-absolute - (org-element-timestamp-interpreter date-element 'ignore)) - target-day-number)) - (error "Unknown date-element type: %s" (org-element-property :type date-element))))) - (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) - -(defsubst org-agenda-ng--date-plain-p (&optional comparator target-date) - (org-agenda-ng--date-p :date comparator target-date)) -(defsubst org-agenda-ng--deadline-p (&optional comparator target-date) - ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries - ;; that have any deadline. But the common case of wanting to select entries whose deadline is - ;; within the warning days (either the global setting or that entry's setting) requires the user - ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that - ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of - ;; course, that would make the deadline selector different from the scheduled, closed, and date - ;; selectors, which would also be unintuitive. - (org-agenda-ng--date-p :deadline comparator target-date)) -(defsubst org-agenda-ng--scheduled-p (&optional comparator target-date) - (org-agenda-ng--date-p :scheduled comparator target-date)) -(defsubst org-agenda-ng--closed-p (&optional comparator target-date) - (org-agenda-ng--date-p :closed comparator target-date)) - -(defmacro org-agenda-ng--priority-p (&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." - (let* (comparator) - (cond ((null priority) - ;; No comparator given: compare only given priority with = - (setq priority comparator-or-priority - comparator '=)) - (t - ;; Both comparator and priority given - (setq comparator comparator-or-priority))) - (setq comparator (cl-case comparator - ;; Invert comparator because higher priority means lower number - (< '>) - (> '<) - (<= '>=) - (>= '<=) - (= '=) - (otherwise (user-error "Invalid comparator: %s" comparator)))) - (setq priority (* 1000 (- org-lowest-priority (string-to-char priority)))) - `(when-let ((item-priority (save-excursion - (save-match-data - ;; FIXME: Is the save-match-data above necessary? - (when (and (looking-at org-heading-regexp) - (save-match-data - (string-match org-priority-regexp (match-string 0)))) - ;; TODO: Items with no priority - ;; should not be the same as B - ;; priority. That's not very - ;; useful IMO. Better to do it - ;; like in org-super-agenda. - (org-get-priority (match-string 0))))))) - (funcall ',comparator ,priority item-priority)))) - -(defun org-agenda-ng--habit-p () - (org-is-habit-p)) - -(defun org-ql--regexp-p (regexp) - "Return non-nil if current entry matches REGEXP." - (let ((end (or (save-excursion - (outline-next-heading)) - (point-max)))) - (save-excursion - (goto-char (line-beginning-position)) - (re-search-forward regexp end t)))) - -(defun org-ql--property-p (property &optional value) - "Return non-nil if current entry has PROPERTY, and optionally VALUE." - (pcase property - ('nil (user-error "Property matcher requires a PROPERTY argument.")) - (_ (pcase value - ('nil - ;; Check that PROPERTY exists - (org-entry-get (point) property)) - (_ - ;; Check that PROPERTY has VALUE - (string-equal value (org-entry-get (point) property 'selective))))))) diff --git a/org-ql.el b/org-ql.el new file mode 100644 index 0000000..49c3152 --- /dev/null +++ b/org-ql.el @@ -0,0 +1,238 @@ +;;; Code: + +;;;; Requirements + +(require 'cl-lib) +(require 'org) +(require 'seq) + +(require 'dash) + +;;;; Variables + +(defvar org-ql--today nil) + +;;;; Macros + +(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element)))) + "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. + +ACTION-FN should take a single argument, which will be the result +of calling `org-element-headline-parser' at each matching entry." + (declare (indent defun)) + `(org-ql--query ,files + (byte-compile (lambda () + (cl-symbol-macrolet ((= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body))) + #',action-fn)) + +(defmacro org-ql--fmap (fns &rest body) + (declare (indent defun)) + `(cl-letf ,(cl-loop for (fn target) in fns + collect `((symbol-function ',fn) + (symbol-function ,target))) + ,@body)) + +;;;; Functions + +(cl-defun org-ql--query (files pred action-fn) + (setq files (cl-typecase files + (null (list (buffer-file-name (current-buffer)))) + (list files) + (string (list files)))) + (mapc 'find-file-noselect files) + (let* ((org-use-tag-inheritance t) + (org-scanner-tags nil) + (org-trust-scanner-tags t) + (org-ql--today (org-today))) + (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) + (mapcar action-fn + (org-ql--filter-buffer :pred pred))) + files)))) + +(cl-defun org-ql--filter-buffer (&key pred) + "Return positions of matching headings in current buffer. +Headings should return non-nil for any ANY-PREDS and nil for all +NONE-PREDS." + ;; Cache `org-today' so we don't have to run it repeatedly. + (cl-letf ((today org-ql--today)) + (org-ql--fmap ((category #'org-ql--category-p) + (date #'org-ql--date-plain-p) + (deadline #'org-ql--deadline-p) + (scheduled #'org-ql--scheduled-p) + (closed #'org-ql--closed-p) + (habit #'org-ql--habit-p) + (priority #'org-ql--priority-p) + (todo #'org-ql--todo-p) + (done #'org-ql--done-p) + (tags #'org-ql--tags-p) + (property #'org-ql--property-p) + (regexp #'org-ql--regexp-p) + (org-back-to-heading #'outline-back-to-heading)) + (org-with-wide-buffer + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (org-element-headline-parser (line-end-position)) + while (outline-next-heading)))))) + +;;;;; Predicates + +(defun org-ql--category-p (&rest categories) + "Return non-nil if current heading is in one or more of CATEGORIES." + (when-let ((category (org-get-category (point)))) + (cl-typecase categories + (null t) + (otherwise (member category categories))))) + +(defun org-ql--todo-p (&rest keywords) + "Return non-nil if current heading is a TODO item. +With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." + (when-let ((state (org-get-todo-state))) + (cl-typecase keywords + (null t) + (list (member state keywords)) + (symbol (member state (symbol-value keywords))) + (otherwise (user-error "Invalid todo keywords: %s" keywords))))) + +(defsubst org-ql--done-p () + (apply #'org-ql--todo-p org-done-keywords-for-agenda)) + +(defun org-ql--tags-p (&rest tags) + "Return non-nil if current heading has TAGS." + ;; TODO: Try to use `org-make-tags-matcher' to improve performance. + (when-let ((tags-at (org-get-tags-at (point) + ;; FIXME: Would be nice to not check this for every heading checked. + ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. + ;; (not (member 'agenda org-agenda-use-tag-inheritance)) + org-use-tag-inheritance))) + (cl-typecase tags + (null t) + (otherwise (seq-intersection tags tags-at))))) + +(defun org-agenda-ng--date-p (type &optional comparator target-date) + "Return non-nil if current heading has a date property of TYPE. +TYPE should be a keyword symbol, like :scheduled or :deadline. + +With COMPARATOR and TARGET-DATE, return non-nil if entry's +scheduled date compares with TARGET-DATE according to COMPARATOR. +TARGET-DATE may be a string like \"2017-08-05\", or an integer +like one returned by `date-to-day'." + (when-let ((timestamp (pcase type + ;; FIXME: Add :date selector, since I put it + ;; in the examples but forgot to actually + ;; make it. + (:deadline (org-entry-get (point) "DEADLINE")) + (:scheduled (org-entry-get (point) "SCHEDULED")) + (:closed (org-entry-get (point) "CLOSED")))) + (date-element (with-temp-buffer + ;; FIXME: Hack: since we're using + ;; (org-element-property :type date-element) + ;; below, we need this date parsed into an + ;; org-element element + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)))) + (pcase comparator + ;; Not comparing, just checking if it has one + ('nil t) + ;; Compare dates + ((pred functionp) + (let ((target-day-number (cl-typecase target-date + (null (+ (org-get-wdays timestamp) (org-today))) + ;; Append time to target-date + ;; because `date-to-day' requires it + (string (date-to-day (concat target-date " 00:00"))) + (integer target-date)))) + (pcase (org-element-property :type date-element) + ((or 'active 'inactive) + (funcall comparator + (org-time-string-to-absolute + (org-element-timestamp-interpreter date-element 'ignore)) + target-day-number)) + (error "Unknown date-element type: %s" (org-element-property :type date-element))))) + (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) + +(defsubst org-ql--date-plain-p (&optional comparator target-date) + (org-agenda-ng--date-p :date comparator target-date)) +(defsubst org-ql--deadline-p (&optional comparator target-date) + ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries + ;; that have any deadline. But the common case of wanting to select entries whose deadline is + ;; within the warning days (either the global setting or that entry's setting) requires the user + ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that + ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of + ;; course, that would make the deadline selector different from the scheduled, closed, and date + ;; selectors, which would also be unintuitive. + (org-agenda-ng--date-p :deadline comparator target-date)) +(defsubst org-ql--scheduled-p (&optional comparator target-date) + (org-agenda-ng--date-p :scheduled comparator target-date)) +(defsubst org-ql--closed-p (&optional comparator target-date) + (org-agenda-ng--date-p :closed comparator target-date)) + +(defmacro org-ql--priority-p (&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." + (let* (comparator) + (cond ((null priority) + ;; No comparator given: compare only given priority with = + (setq priority comparator-or-priority + comparator '=)) + (t + ;; Both comparator and priority given + (setq comparator comparator-or-priority))) + (setq comparator (cl-case comparator + ;; Invert comparator because higher priority means lower number + (< '>) + (> '<) + (<= '>=) + (>= '<=) + (= '=) + (otherwise (user-error "Invalid comparator: %s" comparator)))) + (setq priority (* 1000 (- org-lowest-priority (string-to-char priority)))) + `(when-let ((item-priority (save-excursion + (save-match-data + ;; FIXME: Is the save-match-data above necessary? + (when (and (looking-at org-heading-regexp) + (save-match-data + (string-match org-priority-regexp (match-string 0)))) + ;; TODO: Items with no priority + ;; should not be the same as B + ;; priority. That's not very + ;; useful IMO. Better to do it + ;; like in org-super-agenda. + (org-get-priority (match-string 0))))))) + (funcall ',comparator ,priority item-priority)))) + +(defun org-ql--habit-p () + (org-is-habit-p)) + +(defun org-ql--regexp-p (regexp) + "Return non-nil if current entry matches REGEXP." + (let ((end (or (save-excursion + (outline-next-heading)) + (point-max)))) + (save-excursion + (goto-char (line-beginning-position)) + (re-search-forward regexp end t)))) + +(defun org-ql--property-p (property &optional value) + "Return non-nil if current entry has PROPERTY, and optionally VALUE." + (pcase property + ('nil (user-error "Property matcher requires a PROPERTY argument.")) + (_ (pcase value + ('nil + ;; Check that PROPERTY exists + (org-entry-get (point) property)) + (_ + ;; Check that PROPERTY has VALUE + (string-equal value (org-entry-get (point) property 'selective))))))) + +(provide 'org-ql) From d1f26eec2f29a3156a3389bd22c50a203bd1e334 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 22 May 2018 06:27:21 -0500 Subject: [PATCH 058/970] (org-ql--priority-p) Convert to function I don't remember why I had made it a macro, but it needs to be a function so it can be called correctly in org-ql--query. --- org-ql.el | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/org-ql.el b/org-ql.el index 49c3152..49c60e3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -174,7 +174,7 @@ like one returned by `date-to-day'." (defsubst org-ql--closed-p (&optional comparator target-date) (org-agenda-ng--date-p :closed comparator target-date)) -(defmacro org-ql--priority-p (&optional comparator-or-priority priority) +(defun org-ql--priority-p (&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 (\` =) @@ -197,19 +197,19 @@ comparator, PRIORITY should be a priority string." (= '=) (otherwise (user-error "Invalid comparator: %s" comparator)))) (setq priority (* 1000 (- org-lowest-priority (string-to-char priority)))) - `(when-let ((item-priority (save-excursion - (save-match-data - ;; FIXME: Is the save-match-data above necessary? - (when (and (looking-at org-heading-regexp) - (save-match-data - (string-match org-priority-regexp (match-string 0)))) - ;; TODO: Items with no priority - ;; should not be the same as B - ;; priority. That's not very - ;; useful IMO. Better to do it - ;; like in org-super-agenda. - (org-get-priority (match-string 0))))))) - (funcall ',comparator ,priority item-priority)))) + (when-let ((item-priority (save-excursion + (save-match-data + ;; FIXME: Is the save-match-data above necessary? + (when (and (looking-at org-heading-regexp) + (save-match-data + (string-match org-priority-regexp (match-string 0)))) + ;; TODO: Items with no priority + ;; should not be the same as B + ;; priority. That's not very + ;; useful IMO. Better to do it + ;; like in org-super-agenda. + (org-get-priority (match-string 0))))))) + (funcall comparator priority item-priority)))) (defun org-ql--habit-p () (org-is-habit-p)) From 1ccbe008ac7f3f21b2793a3e4e8e94b70d72dfdb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 22 May 2018 06:27:53 -0500 Subject: [PATCH 059/970] (org-ql) Remove sharp-quote from action-fn That should be specified from the macro call, not here. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 49c60e3..dc80413 100644 --- a/org-ql.el +++ b/org-ql.el @@ -28,7 +28,7 @@ of calling `org-element-headline-parser' at each matching entry." (<= #'<=) (>= #'>=)) ,pred-body))) - #',action-fn)) + ,action-fn)) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun)) From d826425fd7acad440eb310783ee074f20490e101 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 03:22:25 -0500 Subject: [PATCH 060/970] Add: Sorting for org-ql --- README.org | 16 +++++++++ notes.org | 12 +++++++ org-ql.el | 97 +++++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 114 insertions(+), 11 deletions(-) diff --git a/README.org b/README.org index 0fc298e..3758a90 100644 --- a/README.org +++ b/README.org @@ -76,3 +76,19 @@ Another way to look at it is like a "query language" for Org buffers. For examp #+END_SRC Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. + +Results may also be sorted by a user-defined sorting function, or by some built-in sorters: =date=, =deadline=, =scheduled=, =priority= (which assume that the =action-fn= is the default, =org-element-headline-parser)=. For example: + +#+BEGIN_SRC elisp + ;; Return TODO items sorted by deadline, then priority. These built-in sorters assume that items + ;; are Org elements returned by `org-element-headline-parser' (the default action function). + (org-ql "~/org/main.org" + (todo) + :sort (deadline priority)) + + ;; Return TODO items sorted by user-defined sorting function. + (org-ql "~/org/main.org" + (todo) + :sort #'custom-sort-fn) +#+END_SRC + diff --git a/notes.org b/notes.org index 018ae07..ab3cc4f 100644 --- a/notes.org +++ b/notes.org @@ -176,6 +176,18 @@ Doesn't seem to make any difference. (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)) +#+END_SRC + ** Regexp matching #+BEGIN_SRC elisp diff --git a/org-ql.el b/org-ql.el index dc80413..c8f898c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -14,21 +14,30 @@ ;;;; Macros -(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element)))) +(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element))) sort) "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result -of calling `org-element-headline-parser' at each matching entry." +of calling `org-element-headline-parser' at each matching entry. + +SORT is a user defined sorting function, or an unquoted list of +one or more sorting methods, including: `date', `deadline', +`scheduled', and `priority'." (declare (indent defun)) - `(org-ql--query ,files - (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,pred-body))) - ,action-fn)) + `(let ((items (org-ql--query ,files + (byte-compile (lambda () + (cl-symbol-macrolet ((= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body))) + ,action-fn))) + (cl-typecase ',sort + (list (org-ql--sort-by items ',sort)) + (function (funcall ,sort items)) + (null items) + (t (user-error "SORT must be a function or a list of methods (see documentation)"))))) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun)) @@ -235,4 +244,70 @@ comparator, PRIORITY should be a priority string." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) +;;;;; Sorting + +;; FIXME: These appear to work properly, but it would be good to have tests for them. + +(defun org-ql--sort-by (items predicates) + "Return ITEMS sorted by PREDICATES. +PREDICATES is a list of one or more sorting methods, including: +`deadline', `scheduled', and `priority'." + ;; FIXME: Test `date' type. + (cl-flet ((sorter (symbol) + (pcase symbol + ((or 'deadline 'scheduled) + (apply-partially #'org-ql--date-type< (intern (concat ":" (symbol-name symbol))))) + ('date #'org-ql--date<) + ('priority #'org-ql--priority<) + ;; FIXME: Add more? + (_ (user-error "Invalid sorting predicate: %s" symbol))))) + (cl-loop for pred in (nreverse predicates) + do (setq items (-sort (sorter pred) items)) + finally return items))) + +(defun org-ql--date-type< (type a b) + "Return non-nil if A's date of TYPE is earlier than B's. +A and B are Org headline elements. TYPE should be a symbol like +`:deadline' or `:scheduled'" + (org-ql--org-timestamp-element< (org-element-property type (car a)) + (org-element-property type (car b)))) + +(defun org-ql--date< (a b) + "Return non-nil if A's deadline or scheduled element property is earlier than B's. +Deadline is considered before scheduled." + (cl-flet ((ts (item) + (or (org-element-property :deadline (car item)) + (org-element-property :scheduled (car item))))) + (org-ql--org-timestamp-element< (ts a) (ts b)))) + +(defun org-ql--org-timestamp-element< (a b) + "Return non-nil if A's date element is earlier than B's. +A and B are Org timestamp elements." + (cl-flet ((ts (ts) + (when ts + (org-timestamp-format ts "%s")))) + (let* ((a-ts (ts a)) + (b-ts (ts b))) + (cond ((and a-ts b-ts) + (string< a-ts b-ts)) + (a-ts t) + (b-ts nil))))) + +(defun org-ql--priority< (a b) + "Return non-nil if A's priority is higher than B's. +A and B are Org headline elements." + (cl-flet ((priority (item) + (org-element-property :priority (car item)))) + ;; NOTE: Priorities are numbers in Org elements. This might differ from the priority selector logic. + (let ((a-priority (priority a)) + (b-priority (priority b))) + (cond ((and a-priority b-priority) + (< a-priority b-priority)) + (a-priority t) + (b-priority nil))))) + +;;;; Footer + (provide 'org-ql) + +;;; org-ql.el ends here From 70573b98c5ffcea48d46600cd7b0070b1dd79bdf Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 07:01:29 -0500 Subject: [PATCH 061/970] Fix: Remove unnecessary list from default action Not sure why I had put that in there... --- org-ql.el | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/org-ql.el b/org-ql.el index c8f898c..3bf4030 100644 --- a/org-ql.el +++ b/org-ql.el @@ -14,7 +14,7 @@ ;;;; Macros -(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) (list element))) sort) +(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) element)) sort) "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result @@ -269,15 +269,15 @@ PREDICATES is a list of one or more sorting methods, including: "Return non-nil if A's date of TYPE is earlier than B's. A and B are Org headline elements. TYPE should be a symbol like `:deadline' or `:scheduled'" - (org-ql--org-timestamp-element< (org-element-property type (car a)) - (org-element-property type (car b)))) + (org-ql--org-timestamp-element< (org-element-property type a) + (org-element-property type b))) (defun org-ql--date< (a b) "Return non-nil if A's deadline or scheduled element property is earlier than B's. Deadline is considered before scheduled." (cl-flet ((ts (item) - (or (org-element-property :deadline (car item)) - (org-element-property :scheduled (car item))))) + (or (org-element-property :deadline item) + (org-element-property :scheduled item)))) (org-ql--org-timestamp-element< (ts a) (ts b)))) (defun org-ql--org-timestamp-element< (a b) @@ -297,7 +297,7 @@ A and B are Org timestamp elements." "Return non-nil if A's priority is higher than B's. A and B are Org headline elements." (cl-flet ((priority (item) - (org-element-property :priority (car item)))) + (org-element-property :priority item))) ;; NOTE: Priorities are numbers in Org elements. This might differ from the priority selector logic. (let ((a-priority (priority a)) (b-priority (priority b))) From edc9958aa1f7426ed81e8551b62d52e289f0f751 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 07:03:28 -0500 Subject: [PATCH 062/970] Add: Sorting by TODO keyword --- notes.org | 4 ++++ org-ql.el | 36 +++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/notes.org b/notes.org index ab3cc4f..b681629 100644 --- a/notes.org +++ b/notes.org @@ -186,6 +186,10 @@ Doesn't seem to make any difference. (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 ** Regexp matching diff --git a/org-ql.el b/org-ql.el index 3bf4030..412ca13 100644 --- a/org-ql.el +++ b/org-ql.el @@ -253,16 +253,34 @@ comparator, PRIORITY should be a priority string." PREDICATES is a list of one or more sorting methods, including: `deadline', `scheduled', and `priority'." ;; FIXME: Test `date' type. - (cl-flet ((sorter (symbol) - (pcase symbol - ((or 'deadline 'scheduled) - (apply-partially #'org-ql--date-type< (intern (concat ":" (symbol-name symbol))))) - ('date #'org-ql--date<) - ('priority #'org-ql--priority<) - ;; FIXME: Add more? - (_ (user-error "Invalid sorting predicate: %s" symbol))))) + (cl-flet* ((sorter (symbol) + (pcase symbol + ((or 'deadline 'scheduled) + (apply-partially #'org-ql--date-type< (intern (concat ":" (symbol-name symbol))))) + ('date #'org-ql--date<) + ('priority #'org-ql--priority<) + ;; NOTE: 'todo is handled below + ;; FIXME: Add more? + (_ (user-error "Invalid sorting predicate: %s" symbol)))) + (todo-keyword-pos (keyword) + ;; MAYBE: Would it be faster to precompute these and do an alist lookup? + (cl-position keyword org-todo-keywords-1 :test #'string=)) + (sort-by-todo-keyword (items) + (let* ((grouped-items (--group-by (when-let (keyword (org-element-property :todo-keyword it)) + (substring-no-properties keyword)) + items)) + (sorted-groups (--sort (let* ((it-pos (todo-keyword-pos (car it))) + (other-pos (todo-keyword-pos (car other)))) + (cond ((and it-pos other-pos) + (< it-pos other-pos)) + (it-pos t) + (other-pos nil))) + grouped-items))) + (-flatten-n 1 (-map #'cdr sorted-groups))))) (cl-loop for pred in (nreverse predicates) - do (setq items (-sort (sorter pred) items)) + do (setq items (if (eq pred 'todo) + (sort-by-todo-keyword items) + (-sort (sorter pred) items))) finally return items))) (defun org-ql--date-type< (type a b) From e04c1212a090c2d88b511ad09621d313dcb157d5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 07:03:37 -0500 Subject: [PATCH 063/970] Tidy: Footer --- org-agenda-ng.el | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e6ab117..e8c640c 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -265,3 +265,9 @@ property." (defun org-agenda-ng--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) + +;;;; Footer + +(provide 'org-agenda-ng) + +;;; org-agenda-ng.el ends here From d722e4db7295547147e587e9ab6deaa25426f5c8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 07:26:03 -0500 Subject: [PATCH 064/970] Fix: (--add-priority-face) match-string Oops... --- org-agenda-ng.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index e8c640c..1f862c3 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -163,7 +163,7 @@ Its property list should be the second item in the list, as returned by `org-ele (defun org-agenda-ng--add-priority-face (string) "Return STRING with priority face added." (when (string-match "\\(\\[#\\(.\\)\\]\\)" string) - (let ((face (org-get-priority-face (string-to-char (match-string 2))))) + (let ((face (org-get-priority-face (string-to-char (match-string 2 string))))) (org-add-props string nil 'face face 'font-lock-fontified t)))) (defun org-agenda-ng--add-scheduled-face (element) From a3cb114f717fde1caee584bd8ccf359063f04a01 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 07:49:44 -0500 Subject: [PATCH 065/970] Add: (org-ql) Optionally don't widen buffers --- org-ql.el | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/org-ql.el b/org-ql.el index 412ca13..9663506 100644 --- a/org-ql.el +++ b/org-ql.el @@ -14,7 +14,7 @@ ;;;; Macros -(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) element)) sort) +(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) element)) sort narrow) "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result @@ -22,7 +22,10 @@ of calling `org-element-headline-parser' at each matching entry. SORT is a user defined sorting function, or an unquoted list of one or more sorting methods, including: `date', `deadline', -`scheduled', and `priority'." +`scheduled', and `priority'. + +If NARROW is non-nil, query will run without widening the +buffer (the default is to widen and search the entire buffer)." (declare (indent defun)) `(let ((items (org-ql--query ,files (byte-compile (lambda () @@ -32,7 +35,8 @@ one or more sorting methods, including: `date', `deadline', (<= #'<=) (>= #'>=)) ,pred-body))) - ,action-fn))) + ,action-fn + :narrow ,narrow))) (cl-typecase ',sort (list (org-ql--sort-by items ',sort)) (function (funcall ,sort items)) @@ -48,7 +52,8 @@ one or more sorting methods, including: `date', `deadline', ;;;; Functions -(cl-defun org-ql--query (files pred action-fn) +(cl-defun org-ql--query (files pred action-fn &key narrow) + "FIXME: Add docstring." (setq files (cl-typecase files (null (list (buffer-file-name (current-buffer)))) (list files) @@ -60,13 +65,14 @@ one or more sorting methods, including: `date', `deadline', (org-ql--today (org-today))) (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) (mapcar action-fn - (org-ql--filter-buffer :pred pred))) + (org-ql--filter-buffer :pred pred :narrow narrow))) files)))) -(cl-defun org-ql--filter-buffer (&key pred) +(cl-defun org-ql--filter-buffer (&key pred narrow) "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all -NONE-PREDS." +NONE-PREDS. If NARROW is non-nil, buffer will not be widened +first." ;; Cache `org-today' so we don't have to run it repeatedly. (cl-letf ((today org-ql--today)) (org-ql--fmap ((category #'org-ql--category-p) @@ -82,13 +88,16 @@ NONE-PREDS." (property #'org-ql--property-p) (regexp #'org-ql--regexp-p) (org-back-to-heading #'outline-back-to-heading)) - (org-with-wide-buffer - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (org-element-headline-parser (line-end-position)) - while (outline-next-heading)))))) + (save-excursion + (save-restriction + (unless narrow + (widen)) + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (org-element-headline-parser (line-end-position)) + while (outline-next-heading))))))) ;;;;; Predicates From 6624837aa23322785b4a66d54c7f9886048ea42c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 23 May 2018 09:35:35 -0500 Subject: [PATCH 066/970] Change: Read files or buffers --- org-ql.el | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/org-ql.el b/org-ql.el index 9663506..17e9a50 100644 --- a/org-ql.el +++ b/org-ql.el @@ -14,8 +14,8 @@ ;;;; Macros -(cl-defmacro org-ql (files pred-body &key (action-fn (lambda (element) element)) sort narrow) - "Find entries in FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. +(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn (lambda (element) element)) sort narrow) + "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result of calling `org-element-headline-parser' at each matching entry. @@ -27,7 +27,7 @@ one or more sorting methods, including: `date', `deadline', If NARROW is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer)." (declare (indent defun)) - `(let ((items (org-ql--query ,files + `(let ((items (org-ql--query ,buffers-or-files (byte-compile (lambda () (cl-symbol-macrolet ((= #'=) (< #'<) @@ -52,21 +52,25 @@ buffer (the default is to widen and search the entire buffer)." ;;;; Functions -(cl-defun org-ql--query (files pred action-fn &key narrow) +(cl-defun org-ql--query (buffers-or-files pred action-fn &key narrow) "FIXME: Add docstring." - (setq files (cl-typecase files - (null (list (buffer-file-name (current-buffer)))) - (list files) - (string (list files)))) - (mapc 'find-file-noselect files) + ;; MAYBE: Set :narrow t for buffers and nil for files. + (setq buffers-or-files (cl-typecase buffers-or-files + (null (list (current-buffer))) + (buffer (list buffers-or-files)) + (list buffers-or-files) + (string (list buffers-or-files)))) (let* ((org-use-tag-inheritance t) (org-scanner-tags nil) (org-trust-scanner-tags t) (org-ql--today (org-today))) - (-flatten-n 1 (--map (with-current-buffer (find-buffer-visiting it) + (-flatten-n 1 (--map (with-current-buffer (cl-typecase it + (buffer it) + (string (or (find-buffer-visiting it) + (find-file-noselect it)))) (mapcar action-fn (org-ql--filter-buffer :pred pred :narrow narrow))) - files)))) + buffers-or-files)))) (cl-defun org-ql--filter-buffer (&key pred narrow) "Return positions of matching headings in current buffer. From aa07803635235c8d460db9764dec4464b17f0513 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 09:49:24 -0500 Subject: [PATCH 067/970] Add notes --- notes.org | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/notes.org b/notes.org index b681629..6184670 100644 --- a/notes.org +++ b/notes.org @@ -1,5 +1,32 @@ +* Tasks + +** TODO Move/rename repo to =org-ql= + +Since =org-sidebar= uses it, it probably makes more sense for =org-ql= to be the primary focus of the repo. But it also uses =org-agenda-ng--format-element=, so =org-agenda-ng= probably should be part of that package, too. + +** TODO Document matchers/selectors/predicates + +And maybe pick a single name for them... + ++ =deadline= :: Be sure to explain how it works with regard to the implied date and =today=. ++ =date=, =scheduled= :: No implied date, but supports =today=. + +** TODO Document sorters + +** TODO Add more sorters? + ++ [ ] =category= ++ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry + +** MAYBE Date predicate that searches entire entry + +Because the existing ones only search the special date property line. + +** TODO 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. * Ideas ** DONE Operate on list of heading positions From fd00eb6bb5e961f69edff7e34199e07f30640907 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 09:50:07 -0500 Subject: [PATCH 068/970] Change: second -> cadr --- org-agenda-ng.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 1f862c3..4373e65 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -86,10 +86,10 @@ dates in the past, and negative for dates in the future." (defun org-agenda-ng--add-markers (element) "Return ELEMENT with marker properties added." (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) - (properties (--> (second element) + (properties (--> (cadr element) (plist-put it :org-marker marker) (plist-put it :org-hd-marker marker)))) - (setf (second element) properties) + (setf (cadr element) properties) element)) (defun org-agenda-ng--format-element (element) @@ -97,7 +97,7 @@ dates in the past, and negative for dates in the future." ;; which is a lot. We are a long way from that, but it's a start. "Return ELEMENT as a string with its text-properties set according to its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." - (let* ((properties (second element)) + (let* ((properties (cadr element)) ;; Remove the :parent property, which so bloats the size of ;; the properties list that it makes it essentially ;; impossible to debug, because Emacs takes approximately @@ -212,7 +212,7 @@ Its property list should be the second item in the list, as returned by `org-ele (title (--> (org-element-property :raw-value element) (org-add-props it nil 'face face))) - (properties (--> (second element) + (properties (--> (cadr element) (plist-put it :title title) (plist-put it :relative-due-date relative-due-date))) (prefix (cl-destructuring-bind (first next) org-agenda-scheduled-leaders @@ -254,7 +254,7 @@ property." (title (--> (org-element-property :raw-value element) (org-add-props it nil 'face face))) - (properties (--> (second element) + (properties (--> (cadr element) (plist-put it :title title) (plist-put it :relative-due-date relative-due-date)))) (list (car element) From 52a1deffa263ca27d30a6ee57b14f13d231a672d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 09:50:46 -0500 Subject: [PATCH 069/970] Change: Error if file can't be opened --- org-ql.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 17e9a50..8ecf0ad 100644 --- a/org-ql.el +++ b/org-ql.el @@ -67,7 +67,8 @@ buffer (the default is to widen and search the entire buffer)." (-flatten-n 1 (--map (with-current-buffer (cl-typecase it (buffer it) (string (or (find-buffer-visiting it) - (find-file-noselect it)))) + (find-file-noselect it) + (user-error "Can't open file: %s" it)))) (mapcar action-fn (org-ql--filter-buffer :pred pred :narrow narrow))) buffers-or-files)))) From afad077b04a1e3ca915aead1920f98cb11ca98bb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 09:58:23 -0500 Subject: [PATCH 070/970] Change: Improve error message --- org-ql.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 8ecf0ad..08c10cc 100644 --- a/org-ql.el +++ b/org-ql.el @@ -179,7 +179,8 @@ like one returned by `date-to-day'." (org-element-timestamp-interpreter date-element 'ignore)) target-day-number)) (error "Unknown date-element type: %s" (org-element-property :type date-element))))) - (otherwise (error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string" comparator target-date))))) + (otherwise (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" + comparator target-date))))) (defsubst org-ql--date-plain-p (&optional comparator target-date) (org-agenda-ng--date-p :date comparator target-date)) From 005ad636b27e7018dfe4e575ac7e4d3c89474956 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 09:59:00 -0500 Subject: [PATCH 071/970] Change: Rename org-agenda-ng--date-p -> org-ql--date-p --- org-ql.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/org-ql.el b/org-ql.el index 08c10cc..532d99f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -138,7 +138,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (null t) (otherwise (seq-intersection tags tags-at))))) -(defun org-agenda-ng--date-p (type &optional comparator target-date) +(defun org-ql--date-p (type &optional comparator target-date) "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. @@ -183,7 +183,7 @@ like one returned by `date-to-day'." comparator target-date))))) (defsubst org-ql--date-plain-p (&optional comparator target-date) - (org-agenda-ng--date-p :date comparator target-date)) + (org-ql--date-p :date comparator target-date)) (defsubst org-ql--deadline-p (&optional comparator target-date) ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries ;; that have any deadline. But the common case of wanting to select entries whose deadline is @@ -192,11 +192,11 @@ like one returned by `date-to-day'." ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of ;; course, that would make the deadline selector different from the scheduled, closed, and date ;; selectors, which would also be unintuitive. - (org-agenda-ng--date-p :deadline comparator target-date)) + (org-ql--date-p :deadline comparator target-date)) (defsubst org-ql--scheduled-p (&optional comparator target-date) - (org-agenda-ng--date-p :scheduled comparator target-date)) + (org-ql--date-p :scheduled comparator target-date)) (defsubst org-ql--closed-p (&optional comparator target-date) - (org-agenda-ng--date-p :closed comparator target-date)) + (org-ql--date-p :closed comparator target-date)) (defun org-ql--priority-p (&optional comparator-or-priority priority) "Return non-nil if current heading has a certain priority. From f19f2a4cb4584b4e8baaec80f8bd75a68e547c70 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 10:00:20 -0500 Subject: [PATCH 072/970] Fix: Tag inheritance Hardcoded on for now. --- org-ql.el | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/org-ql.el b/org-ql.el index 532d99f..9377691 100644 --- a/org-ql.el +++ b/org-ql.el @@ -55,14 +55,14 @@ buffer (the default is to widen and search the entire buffer)." (cl-defun org-ql--query (buffers-or-files pred action-fn &key narrow) "FIXME: Add docstring." ;; MAYBE: Set :narrow t for buffers and nil for files. - (setq buffers-or-files (cl-typecase buffers-or-files - (null (list (current-buffer))) - (buffer (list buffers-or-files)) - (list buffers-or-files) - (string (list buffers-or-files)))) - (let* ((org-use-tag-inheritance t) - (org-scanner-tags nil) - (org-trust-scanner-tags t) + (let* ((buffers-or-files (cl-typecase buffers-or-files + (null (list (current-buffer))) + (buffer (list buffers-or-files)) + (list buffers-or-files) + (string (list buffers-or-files)))) + ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. + ;; (org-use-tag-inheritance t) + ;; (org-trust-scanner-tags t) (org-ql--today (org-today))) (-flatten-n 1 (--map (with-current-buffer (cl-typecase it (buffer it) @@ -127,13 +127,10 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (apply #'org-ql--todo-p org-done-keywords-for-agenda)) (defun org-ql--tags-p (&rest tags) - "Return non-nil if current heading has TAGS." - ;; TODO: Try to use `org-make-tags-matcher' to improve performance. - (when-let ((tags-at (org-get-tags-at (point) - ;; FIXME: Would be nice to not check this for every heading checked. - ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. - ;; (not (member 'agenda org-agenda-use-tag-inheritance)) - org-use-tag-inheritance))) + "Return non-nil if current heading has one or more of TAGS." + ;; TODO: Try to use `org-make-tags-matcher' to improve performance. It would be nice to not have + ;; to run `org-get-tags-at' for every heading, especially with inheritance. + (when-let ((tags-at (org-get-tags-at (point) (not org-use-tag-inheritance)))) (cl-typecase tags (null t) (otherwise (seq-intersection tags tags-at))))) From 1143414f67bbe751665b8818b1d635bfaf65b2ee Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 24 May 2018 10:04:34 -0500 Subject: [PATCH 073/970] Change: (--date<) Use macrolet instead of flet --- org-ql.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 9377691..7a9755f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -305,9 +305,9 @@ A and B are Org headline elements. TYPE should be a symbol like (defun org-ql--date< (a b) "Return non-nil if A's deadline or scheduled element property is earlier than B's. Deadline is considered before scheduled." - (cl-flet ((ts (item) - (or (org-element-property :deadline item) - (org-element-property :scheduled item)))) + (cl-macrolet ((ts (item) + `(or (org-element-property :deadline ,item) + (org-element-property :scheduled ,item)))) (org-ql--org-timestamp-element< (ts a) (ts b)))) (defun org-ql--org-timestamp-element< (a b) From 977e9aa0a21aa355eb60262663c0f3b86b3e5a2d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:03:21 -0500 Subject: [PATCH 074/970] Change: Enable lexical-binding Hopefully this doesn't break anything... --- org-ql.el | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/org-ql.el b/org-ql.el index 7a9755f..1699db6 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1,3 +1,6 @@ +;; -*- lexical-binding: t; -*- + + ;;; Code: ;;;; Requirements @@ -79,30 +82,31 @@ Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS. If NARROW is non-nil, buffer will not be widened first." ;; Cache `org-today' so we don't have to run it repeatedly. - (cl-letf ((today org-ql--today)) - (org-ql--fmap ((category #'org-ql--category-p) - (date #'org-ql--date-plain-p) - (deadline #'org-ql--deadline-p) - (scheduled #'org-ql--scheduled-p) - (closed #'org-ql--closed-p) - (habit #'org-ql--habit-p) - (priority #'org-ql--priority-p) - (todo #'org-ql--todo-p) - (done #'org-ql--done-p) - (tags #'org-ql--tags-p) - (property #'org-ql--property-p) - (regexp #'org-ql--regexp-p) - (org-back-to-heading #'outline-back-to-heading)) - (save-excursion - (save-restriction - (unless narrow - (widen)) - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (org-element-headline-parser (line-end-position)) - while (outline-next-heading))))))) + (let (today) + (cl-letf ((today org-ql--today)) + (org-ql--fmap ((category #'org-ql--category-p) + (date #'org-ql--date-plain-p) + (deadline #'org-ql--deadline-p) + (scheduled #'org-ql--scheduled-p) + (closed #'org-ql--closed-p) + (habit #'org-ql--habit-p) + (priority #'org-ql--priority-p) + (todo #'org-ql--todo-p) + (done #'org-ql--done-p) + (tags #'org-ql--tags-p) + (property #'org-ql--property-p) + (regexp #'org-ql--regexp-p) + (org-back-to-heading #'outline-back-to-heading)) + (save-excursion + (save-restriction + (unless narrow + (widen)) + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (org-element-headline-parser (line-end-position)) + while (outline-next-heading)))))))) ;;;;; Predicates From 73925c8f1c09d4f479b856ac2c19dd17428ffbab Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:04:01 -0500 Subject: [PATCH 075/970] Change: Use org-done-keywords instead of org-done-keywords-for-agenda This should fix a bug, and it seems like the more correct thing to do. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 1699db6..fcb9f9a 100644 --- a/org-ql.el +++ b/org-ql.el @@ -128,7 +128,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (otherwise (user-error "Invalid todo keywords: %s" keywords))))) (defsubst org-ql--done-p () - (apply #'org-ql--todo-p org-done-keywords-for-agenda)) + (or (apply #'org-ql--todo-p org-done-keywords))) (defun org-ql--tags-p (&rest tags) "Return non-nil if current heading has one or more of TAGS." From a134e34fd887435aa087088f3936573c604d3b9e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:05:17 -0500 Subject: [PATCH 076/970] Change: Improve TODO grouping --- org-ql.el | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index fcb9f9a..b1d5f76 100644 --- a/org-ql.el +++ b/org-ql.el @@ -285,13 +285,11 @@ PREDICATES is a list of one or more sorting methods, including: (let* ((grouped-items (--group-by (when-let (keyword (org-element-property :todo-keyword it)) (substring-no-properties keyword)) items)) - (sorted-groups (--sort (let* ((it-pos (todo-keyword-pos (car it))) - (other-pos (todo-keyword-pos (car other)))) - (cond ((and it-pos other-pos) - (< it-pos other-pos)) - (it-pos t) - (other-pos nil))) - grouped-items))) + (sorted-groups (cl-sort grouped-items #'< + :key (lambda (keyword) + (or (cl-position (car keyword) org-todo-keywords-1 :test #'string=) + ;; 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) do (setq items (if (eq pred 'todo) From 86d2e38802d052ad6684a495de0416bd24dbe7b6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:05:52 -0500 Subject: [PATCH 077/970] Add: (org-ql--fmap) Add debug declaration --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index b1d5f76..02e2a76 100644 --- a/org-ql.el +++ b/org-ql.el @@ -47,7 +47,7 @@ buffer (the default is to widen and search the entire buffer)." (t (user-error "SORT must be a function or a list of methods (see documentation)"))))) (defmacro org-ql--fmap (fns &rest body) - (declare (indent defun)) + (declare (indent defun) (debug (listp body))) `(cl-letf ,(cl-loop for (fn target) in fns collect `((symbol-function ',fn) (symbol-function ,target))) From 27fb5f0852af70b53dbb0abc54865d0a243308e9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:06:24 -0500 Subject: [PATCH 078/970] Comment: Add MAYBE --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index 02e2a76..31c48e0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -269,6 +269,7 @@ comparator, PRIORITY should be a priority string." PREDICATES is a list of one or more sorting methods, including: `deadline', `scheduled', and `priority'." ;; FIXME: Test `date' type. + ;; MAYBE: Use macrolet instead of flet. (cl-flet* ((sorter (symbol) (pcase symbol ((or 'deadline 'scheduled) From 51a472ffa8aa0365e0bf76ee95ea57c03e683940 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 8 Jun 2018 18:06:31 -0500 Subject: [PATCH 079/970] Add: --sanity-check-form function Currently unused, but may try to use it in the future to avoid confusing problems. --- org-ql.el | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/org-ql.el b/org-ql.el index 31c48e0..30cfe54 100644 --- a/org-ql.el +++ b/org-ql.el @@ -76,6 +76,23 @@ buffer (the default is to widen and search the entire buffer)." (org-ql--filter-buffer :pred pred :narrow narrow))) buffers-or-files)))) +(defun org-ql--sanity-check-form (form) + "Signal an error if any of the forms in BODY do not have their preconditions met. +Or, when possible, fix the problem." + (cl-flet ((check (symbol) + (cl-case symbol + ('done (unless org-done-keywords + ;; NOTE: This check needs to be done from within the Org buffer being checked. + (error "Variable `org-done-keywords' is nil. Are you running this from an Org buffer?"))) + ('habit (unless (featurep 'org-habit) + (require 'org-habit)))))) + (cl-loop for elem in form + if (consp elem) + do (progn + (check (car elem)) + (org-ql--sanity-check-form (cdr elem))) + else do (check elem)))) + (cl-defun org-ql--filter-buffer (&key pred narrow) "Return positions of matching headings in current buffer. Headings should return non-nil for any ANY-PREDS and nil for all From c605ccbaf3e6ebbc8b5126adf8e0837ce25d4cc9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Jul 2018 08:26:55 -0500 Subject: [PATCH 080/970] Change: (org-ql--org-timestamp-element<) Use macrolet Should be a small performance improvement, avoiding funcall overhead. --- org-ql.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 30cfe54..cac8297 100644 --- a/org-ql.el +++ b/org-ql.el @@ -333,9 +333,9 @@ Deadline is considered before scheduled." (defun org-ql--org-timestamp-element< (a b) "Return non-nil if A's date element is earlier than B's. A and B are Org timestamp elements." - (cl-flet ((ts (ts) - (when ts - (org-timestamp-format ts "%s")))) + (cl-macrolet ((ts (ts) + `(when ,ts + (org-timestamp-format ,ts "%s")))) (let* ((a-ts (ts a)) (b-ts (ts b))) (cond ((and a-ts b-ts) From 8bfb65d715d72380d10086ef8f3cccdc331088a3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Jul 2018 08:27:54 -0500 Subject: [PATCH 081/970] Change: Refactor, improve docstrings, argument handling, etc. Move some code between functions and macros to make more sense and be more flexible. --- org-agenda-ng.el | 68 ++++++++++++++++++++++++++++++++++++++---------- org-ql.el | 56 +++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 40 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 4373e65..f0b6dff 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -41,26 +41,66 @@ ;; FIXME: DRY these two macros. -(cl-defmacro org-agenda-ng (files pred-body) - "Display an agenda-like buffer of entries in FILES that match PRED-BODY." - (declare (indent defun)) - `(org-agenda-ng--agenda ,files - (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,pred-body))) - #'org-agenda-ng--format-element)) +(cl-defmacro org-agenda-ng (&rest args) + "Display an agenda-like buffer of entries in FILES that match PRED. + +FILES-OR-PRED is a sexp that is evaluated to get the list of +files to scan. + +PRED is a predicate sexp which is evaluated on each entry to test +whether it matches. This should be a form used by `org-ql'. + +The predicate may be passed as FILES-OR-PRED and PRED may be left +nil, in which case the list of files will automatically be set to +the value of calling `org-agenda-files'. + +SORT is a list of sorting keys: `deadline', `scheduled', +`date' (matching either `deadline' or `scheduled'), `priority', +or `todo'. + +NARROW, when non-nil, means to respect narrowing in buffers. +When nil, buffers are widened before being searched." + (declare (indent defun) + (advertised-calling-convention '(files-or-pred &optional pred &key sort narrow) nil)) + (cl-macrolet ((set-keyword-args (args) + `(setq sort (plist-get ,args :sort) + narrow (plist-get ,args :narrow)))) + (let ((files '(org-agenda-files)) + pred sort narrow) + ;; Parse args manually (so we can leave FILES nil for a default argument). + (pcase args + (`(,arg-files ,arg-pred . ,(and rest (guard (keywordp (car rest))))) + (setq files arg-files + pred arg-pred) + (set-keyword-args rest)) + (`(,arg-pred . ,(and rest (guard (keywordp (car rest))))) + (setq pred arg-pred) + (set-keyword-args rest))) + ;; Call --agenda + `(org-agenda-ng--agenda ,files + (byte-compile (lambda () + (cl-symbol-macrolet ((= #'=) (< #'<) (> #'>) (<= #'<=) (>= #'>=)) + ,pred))) + :sort ',sort)))) ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-agenda-ng--agenda (files pred action-fn) - (let* ((entries (org-ql--query files pred action-fn)) +(cl-defun org-agenda-ng--agenda (files pred &key action-fn sort) + ;; `org-ql--query' uses `org-element-headline-parser' by default, which we then map + ;; `org-agenda-ng--format-element' across to get formatted, propertized strings for the agenda. + ;; NOTE: `org-element-headline-parser' should remain the low-level action function, because the + ;; sorting functions work on Org elements (so e.g. if we put `org-agenda-ng--format-element' as + ;; the low-level action function, sorting would do nothing, because the sorting functions would + ;; not find any data to sort on). IOW we have to call `org-agenda-ng--format-element' here, not + ;; pass it to lower functions. + (declare (indent defun)) + (let* ((entries (mapcar #'org-agenda-ng--format-element + (org-ql--query files + pred + :sort sort))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer diff --git a/org-ql.el b/org-ql.el index cac8297..71bc772 100644 --- a/org-ql.el +++ b/org-ql.el @@ -17,7 +17,7 @@ ;;;; Macros -(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn (lambda (element) element)) sort narrow) +(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn '#'identity) sort narrow) "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result @@ -30,21 +30,19 @@ one or more sorting methods, including: `date', `deadline', If NARROW is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer)." (declare (indent defun)) - `(let ((items (org-ql--query ,buffers-or-files - (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,pred-body))) - ,action-fn - :narrow ,narrow))) - (cl-typecase ',sort - (list (org-ql--sort-by items ',sort)) - (function (funcall ,sort items)) - (null items) - (t (user-error "SORT must be a function or a list of methods (see documentation)"))))) + `(org-ql--query ,buffers-or-files + (byte-compile (lambda () + (cl-symbol-macrolet ((= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body))) + :action-fn ,action-fn + :narrow ,narrow + :sort ,(pcase sort + (`(function ,_) sort) + (_ (list 'quote sort))))) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun) (debug (listp body))) @@ -55,9 +53,10 @@ buffer (the default is to widen and search the entire buffer)." ;;;; Functions -(cl-defun org-ql--query (buffers-or-files pred action-fn &key narrow) +(cl-defun org-ql--query (buffers-or-files pred &key (action-fn #'identity) narrow sort) "FIXME: Add docstring." ;; MAYBE: Set :narrow t for buffers and nil for files. + (declare (indent defun)) (let* ((buffers-or-files (cl-typecase buffers-or-files (null (list (current-buffer))) (buffer (list buffers-or-files)) @@ -66,15 +65,20 @@ buffer (the default is to widen and search the entire buffer)." ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) - (org-ql--today (org-today))) - (-flatten-n 1 (--map (with-current-buffer (cl-typecase it - (buffer it) - (string (or (find-buffer-visiting it) - (find-file-noselect it) - (user-error "Can't open file: %s" it)))) - (mapcar action-fn - (org-ql--filter-buffer :pred pred :narrow narrow))) - buffers-or-files)))) + (org-ql--today (org-today)) + (items (-flatten-n 1 (--map (with-current-buffer (cl-typecase it + (buffer it) + (string (or (find-buffer-visiting it) + (find-file-noselect it) + (user-error "Can't open file: %s" it)))) + (mapcar action-fn + (org-ql--filter-buffer :pred pred :narrow narrow))) + buffers-or-files)))) + (cl-typecase sort + (list (org-ql--sort-by items sort)) + (function (funcall sort items)) + (null items) + (t (user-error "SORT must be a function or a list of methods (see documentation)"))))) (defun org-ql--sanity-check-form (form) "Signal an error if any of the forms in BODY do not have their preconditions met. From 3ec6ded312f35449a75097174a771e0edc949ead Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Jul 2018 08:29:09 -0500 Subject: [PATCH 082/970] Notes: Add note --- notes.org | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/notes.org b/notes.org index 6184670..f90a3fb 100644 --- a/notes.org +++ b/notes.org @@ -27,6 +27,12 @@ Because the existing ones only search the special date property line. ** TODO 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 * Ideas ** DONE Operate on list of heading positions From ed55f7f15faa1c9dd70e6d8405258faadeb2ef05 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Jul 2018 08:36:24 -0500 Subject: [PATCH 083/970] Notes: Add notes --- notes.org | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/notes.org b/notes.org index f90a3fb..e17bcef 100644 --- a/notes.org +++ b/notes.org @@ -1,4 +1,4 @@ - +#+PROPERTY: LOGGING nil * Tasks @@ -35,6 +35,22 @@ If your function needs to retrieve the tags including inherited tags at the *cur #+END_QUOTE * Ideas +** SOMEDAY Dual matching with regexp and predicates + +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. + ** DONE Operate on list of heading positions CLOSED: [2018-05-10 Thu 15:02] :LOGBOOK: From 056c93bcd61539eecf2fdd4d6bbae4af026e279d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 10 Jul 2018 08:38:17 -0500 Subject: [PATCH 084/970] Docs: Add examples and update readme --- README.org | 12 +++++++----- examples.org | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 examples.org diff --git a/README.org b/README.org index 3758a90..99dde6e 100644 --- a/README.org +++ b/README.org @@ -17,19 +17,19 @@ Here's an example of generating a kind of agenda view for today (note that the g Here are some other examples: #+BEGIN_SRC elisp - ;; Show an agenda-like view of items in all agenda files with TODO and SOMEDAY keywords which are + ;; Show an agenda-like view of items in "~/org/main.org" with TODO and SOMEDAY keywords which are ;; tagged "computer" or "Emacs" and in the category "main": - (org-agenda-ng org-agenda-files + (org-agenda-ng "~/org/main.org" (and (todo "TODO" "SOMEDAY") (tags "computer" "Emacs") (category "main"))) - ;; Show an agenda-like view of all habits: - (org-agenda-ng org-agenda-files + ;; Show an agenda-like view of all habits in all agenda files: + (org-agenda-ng (habit)) ;; Show an agenda-like view similar to a "traditional" Org agenda: - (org-agenda-ng "~/org/main.org" + (org-agenda-ng (or (habit) (date = today) (deadline <=) @@ -38,6 +38,8 @@ Here are some other examples: (closed = today)))) #+END_SRC +More examples are available in [[examples.org]]. + ** org-ql Another way to look at it is like a "query language" for Org buffers. For example: diff --git a/examples.org b/examples.org new file mode 100644 index 0000000..7ac0002 --- /dev/null +++ b/examples.org @@ -0,0 +1,20 @@ + + +* Examples + +** Showing TO-READ entries containing the word "lisp" + +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 [[https://orgmode.org/worg/org-tutorials/advanced-searching.html#combining-metadata-and-full-text-queries][advanced searching tutorial]], it would require using ~org-search-view~ with a query with specific regular expression syntax, like this: + +#+BEGIN_EXAMPLE + +lisp +{^\*+\s-+TO-READ\s-} +#+END_EXAMPLE + +But with =org-ql= or =org-agenda-ng=, you would write: + +#+BEGIN_SRC elisp + (org-agenda-ng + (and (regexp "lisp") + (todo "TO-READ"))) +#+END_SRC + From fe32388d5089deefa42732b040ab1e92418d0546 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 1 Aug 2018 10:50:27 -0500 Subject: [PATCH 085/970] Change/Fix: (--format-element) Use marker's buffer When formatting an element outside the element's buffer (e.g. when mapping --format-element across the results of org-ql), the current buffer is not the element's source buffer, so functions like org-get-tags-at will not return the correct results, because they don't use the marker's buffer. So now we set the current buffer to the marker's buffer. As this package matures, this might become unnecessary in the future, but it's probably best to keep it for correctness. --- org-agenda-ng.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index f0b6dff..c572145 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -163,7 +163,9 @@ Its property list should be the second item in the list, as returned by `org-ele (if-let ((marker (or (org-element-property :org-hd-marker element) (org-element-property :org-marker element) (org-element-property :begin element)))) - (org-get-tags-at marker (not org-use-tag-inheritance)) + (with-current-buffer (marker-buffer marker) + ;; I wish `org-get-tags-at' used the correct buffer automatically. + (org-get-tags-at marker (not org-use-tag-inheritance))) ;; No marker found (warn "No marker found for item: %s" title) (org-element-property :tags element)) From 4c045f78ea04a0690bb7bda51070f125accf2636 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 1 Aug 2018 10:52:59 -0500 Subject: [PATCH 086/970] Tidy: Indentation --- org-agenda-ng.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c572145..c6609ed 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -99,8 +99,8 @@ When nil, buffers are widened before being searched." (declare (indent defun)) (let* ((entries (mapcar #'org-agenda-ng--format-element (org-ql--query files - pred - :sort sort))) + pred + :sort sort))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer From fe3d5c2bd80dd52f6d13e1e3f965aa685cbe275f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 1 Aug 2018 10:53:15 -0500 Subject: [PATCH 087/970] Fix: (org-ql) Set "today" to org-ql--today in symbol-macrolet Since we byte-compile the lambda, this is necessary (at least, I think this is why). Remember that we set org-ql--today when we actually run queries. --- org-ql.el | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/org-ql.el b/org-ql.el index 71bc772..73e10dc 100644 --- a/org-ql.el +++ b/org-ql.el @@ -32,7 +32,8 @@ buffer (the default is to widen and search the entire buffer)." (declare (indent defun)) `(org-ql--query ,buffers-or-files (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) (< #'<) (> #'>) (<= #'<=) @@ -103,31 +104,29 @@ Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS. If NARROW is non-nil, buffer will not be widened first." ;; Cache `org-today' so we don't have to run it repeatedly. - (let (today) - (cl-letf ((today org-ql--today)) - (org-ql--fmap ((category #'org-ql--category-p) - (date #'org-ql--date-plain-p) - (deadline #'org-ql--deadline-p) - (scheduled #'org-ql--scheduled-p) - (closed #'org-ql--closed-p) - (habit #'org-ql--habit-p) - (priority #'org-ql--priority-p) - (todo #'org-ql--todo-p) - (done #'org-ql--done-p) - (tags #'org-ql--tags-p) - (property #'org-ql--property-p) - (regexp #'org-ql--regexp-p) - (org-back-to-heading #'outline-back-to-heading)) - (save-excursion - (save-restriction - (unless narrow - (widen)) - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall pred) - collect (org-element-headline-parser (line-end-position)) - while (outline-next-heading)))))))) + (org-ql--fmap ((category #'org-ql--category-p) + (date #'org-ql--date-plain-p) + (deadline #'org-ql--deadline-p) + (scheduled #'org-ql--scheduled-p) + (closed #'org-ql--closed-p) + (habit #'org-ql--habit-p) + (priority #'org-ql--priority-p) + (todo #'org-ql--todo-p) + (done #'org-ql--done-p) + (tags #'org-ql--tags-p) + (property #'org-ql--property-p) + (regexp #'org-ql--regexp-p) + (org-back-to-heading #'outline-back-to-heading)) + (save-excursion + (save-restriction + (unless narrow + (widen)) + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall pred) + collect (org-element-headline-parser (line-end-position)) + while (outline-next-heading)))))) ;;;;; Predicates From 08243d5479cb97f12580636d557e3eb989e4999f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 01:52:23 -0500 Subject: [PATCH 088/970] Add: (org-ql) Markers argument --- org-ql.el | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 73e10dc..b21a750 100644 --- a/org-ql.el +++ b/org-ql.el @@ -17,7 +17,8 @@ ;;;; Macros -(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn '#'identity) sort narrow) +(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn '#'identity) + sort narrow markers) "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. ACTION-FN should take a single argument, which will be the result @@ -28,8 +29,20 @@ one or more sorting methods, including: `date', `deadline', `scheduled', and `priority'. If NARROW is non-nil, query will run without widening the -buffer (the default is to widen and search the entire buffer)." +buffer (the default is to widen and search the entire buffer). + +If MARKERS is non-nil, `org-agenda-ng--add-markers' is used to +add markers to each item, pointing to the item in its source +buffer." (declare (indent defun)) + (when markers + (setq action-fn (pcase action-fn + (`(function identity) '#'org-agenda-ng--add-markers) + (_ (byte-compile `(lambda (item) + (--> item + ;; Add the markers before calling the action fn + org-agenda-ng--add-markers + ,action-fn))))))) `(org-ql--query ,buffers-or-files (byte-compile (lambda () (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda From cc05faa977b40668133d34eac4448f5908090f21 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 15:47:41 -0500 Subject: [PATCH 089/970] Docs: Add missing sort type to docstring --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index b21a750..d232090 100644 --- a/org-ql.el +++ b/org-ql.el @@ -26,7 +26,7 @@ of calling `org-element-headline-parser' at each matching entry. SORT is a user defined sorting function, or an unquoted list of one or more sorting methods, including: `date', `deadline', -`scheduled', and `priority'. +`scheduled', `todo', and `priority'. If NARROW is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). From 334b68de3d9a5c8502b85250cc996b66cab4771d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 15:47:55 -0500 Subject: [PATCH 090/970] Change: (org-ql) Handle arbitrary expressions for sort arg See https://github.com/alphapapa/org-agenda-ng/pull/1 --- org-ql.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index d232090..d15533f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -55,8 +55,14 @@ buffer." :action-fn ,action-fn :narrow ,narrow :sort ,(pcase sort + ;; Custom sort function (`(function ,_) sort) - (_ (list 'quote sort))))) + ((and sort (guard (cl-loop for elem in sort + always (memq elem '(date deadline scheduled todo priority))))) + ;; Default sorting functions + (list 'quote sort)) + ;; Other expression to evaluate + (_ sort)))) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun) (debug (listp body))) From 69083fb17b191bbe86d5b74b776e546a75b8a529 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 16:57:14 -0500 Subject: [PATCH 091/970] Task: Add to-do --- org-agenda-ng.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index c6609ed..a4e344b 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -152,6 +152,11 @@ Its property list should be the second item in the list, as returned by `org-ele for key = (intern (cl-subseq (symbol-name key) 1)) unless (member key '(parent)) append (list key val))) + ;; TODO: --add-faces is used to add the :relative-due-date property, but that fact is + ;; hidden by doing it through --add-faces (which calls --add-scheduled-face and + ;; --add-deadline-face), and doing it in this form that gets the title hides it even more. + ;; Adding the relative due date property should probably be done explicitly and separately + ;; (which would also make it easier to do it independently of faces, etc). (title (--> (org-agenda-ng--add-faces element) (org-element-property :raw-value it) (org-link-display-format it) From 465767e7cc43b0896367253c1a2298da6600f31c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 23:09:21 -0500 Subject: [PATCH 092/970] Add: Outline level predicate Fixes #3. Thanks to @akirak. --- org-ql.el | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/org-ql.el b/org-ql.el index d15533f..260bde9 100644 --- a/org-ql.el +++ b/org-ql.el @@ -135,6 +135,7 @@ first." (tags #'org-ql--tags-p) (property #'org-ql--property-p) (regexp #'org-ql--regexp-p) + (level #'org-ql--level-p) (org-back-to-heading #'outline-back-to-heading)) (save-excursion (save-restriction @@ -178,6 +179,26 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (null t) (otherwise (seq-intersection tags tags-at))))) +(defun org-ql--level-p (level-or-comparator &optional level) + "Return non-nil if current heading's outline level matches LEVEL with COMPARATOR. + +If LEVEL is nil, LEVEL-OR-COMPARATOR should be a level, which +will be tested for equality to the heading's outline level. If +LEVEL is non-nil, LEVEL-OR-COMPARATOR should be a comparator +function. + +Outline levels should be integers." + ;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for + ;; `org-outline-level'. + ;; NOTE: `org-outline-level' accounts for inline tasks, which might be slower than the naive + ;; `org-current-level'. + (when-let ((outline-level (org-outline-level))) + (pcase level + ;; Check for equality + ((pred null) (= outline-level level-or-comparator)) + ;; Check with comparator + (_ (funcall level-or-comparator outline-level level))))) + (defun org-ql--date-p (type &optional comparator target-date) "Return non-nil if current heading has a date property of TYPE. TYPE should be a keyword symbol, like :scheduled or :deadline. From 95d51ef998641b2e1bc0dc9dd23818deef0cf750 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 4 Aug 2018 23:14:44 -0500 Subject: [PATCH 093/970] Comment: Remove comment Benchmarking shows that, when org-ql is byte-compiled, calling org-outline-level is actually slightly faster than org-current-level. --- org-ql.el | 2 -- 1 file changed, 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 260bde9..c18dc76 100644 --- a/org-ql.el +++ b/org-ql.el @@ -190,8 +190,6 @@ function. Outline levels should be integers." ;; NOTE: It might be necessary to take into account `org-odd-levels'; see docstring for ;; `org-outline-level'. - ;; NOTE: `org-outline-level' accounts for inline tasks, which might be slower than the naive - ;; `org-current-level'. (when-let ((outline-level (org-outline-level))) (pcase level ;; Check for equality From 22bf0ae9c07ba9b02dc05efbf380e50ff703467a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 19 Aug 2018 12:10:12 -0500 Subject: [PATCH 094/970] Fix: (org-agenda-ng) Add markers Not sure when I broke this, but this fixes it. Still probably need to refactor a bit, as there's some cross-dependency between org-agenda-ng and org-ql. --- org-agenda-ng.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index a4e344b..a7b259a 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -100,7 +100,8 @@ When nil, buffers are widened before being searched." (let* ((entries (mapcar #'org-agenda-ng--format-element (org-ql--query files pred - :sort sort))) + :sort sort + :action-fn #'org-agenda-ng--add-markers))) (result-string (org-agenda-finalize-entries entries 'agenda)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer From d73175714cf3e230be13b631a98ded7c14f23d4f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 19 Aug 2018 13:21:00 -0500 Subject: [PATCH 095/970] Fix: (org-ql) Work when not sorting Don't know when I broke this. Oops. --- org-ql.el | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/org-ql.el b/org-ql.el index c18dc76..ba39ca5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -55,14 +55,17 @@ buffer." :action-fn ,action-fn :narrow ,narrow :sort ,(pcase sort - ;; Custom sort function - (`(function ,_) sort) - ((and sort (guard (cl-loop for elem in sort - always (memq elem '(date deadline scheduled todo priority))))) + (`(function ,_) + ;; Custom sort function + sort) + ((guard (and sort + (cl-loop for elem in sort + always (memq elem '(date deadline scheduled todo priority))))) ;; Default sorting functions (list 'quote sort)) - ;; Other expression to evaluate - (_ sort)))) + (_ + ;; Other expression to evaluate + sort)))) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun) (debug (listp body))) From 2001c88ed50a03dc4bc433e892179ae38d62ed9f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 19 Aug 2018 13:39:19 -0500 Subject: [PATCH 096/970] Fix: (org-agenda-ng) Handle just query as arguments --- org-agenda-ng.el | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index a7b259a..d96d6f1 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -68,16 +68,24 @@ When nil, buffers are widened before being searched." (let ((files '(org-agenda-files)) pred sort narrow) ;; Parse args manually (so we can leave FILES nil for a default argument). + ;; TODO: DRY this and org-ql, I think. (pcase args (`(,arg-files ,arg-pred . ,(and rest (guard (keywordp (car rest))))) + ;; Files, query, and keyword args (FIXME: Can I combine this and the next one? Does it + ;; matter if rest is nil or starts with a keyword?) (setq files arg-files pred arg-pred) (set-keyword-args rest)) (`(,arg-pred . ,(and rest (guard (keywordp (car rest))))) + ;; Query and keyword args, no files (setq pred arg-pred) - (set-keyword-args rest))) + (set-keyword-args rest)) + (`(,arg-pred) + ;; Only query + (setq pred arg-pred))) ;; Call --agenda `(org-agenda-ng--agenda ,files + ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. (byte-compile (lambda () (cl-symbol-macrolet ((= #'=) (< #'<) (> #'>) (<= #'<=) (>= #'>=)) ,pred))) From 9cce826bfe17e51c4c4e6a881c5ba601086393cd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 19 Aug 2018 14:01:59 -0500 Subject: [PATCH 097/970] Fix: Sorting By using s-join instead of org-agenda-finalize-entries, which does its own sorting. We don't need anything it does, at least not now, and if we ever do, we'll probably want to reimplement it, anyway. HOWEVER, this breaks org-super-agenda, which uses advice to that function to group items. So we need to either figure out another approach (which I have been unable to do so far, trying cl-letf, cl-flet, and advice-add with unwind-protect), or make this depend on org-super-agenda. --- org-agenda-ng.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index d96d6f1..2b906fe 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -110,7 +110,7 @@ When nil, buffers are widened before being searched." pred :sort sort :action-fn #'org-agenda-ng--add-markers))) - (result-string (org-agenda-finalize-entries entries 'agenda)) + (result-string (s-join "\n" entries)) (target-buffer (get-buffer-create "test-agenda-ng"))) (with-current-buffer target-buffer (read-only-mode -1) From 14351e617d4e9a1c3422198ec655a8e1f8c99048 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 06:18:23 -0500 Subject: [PATCH 098/970] Change: Handle sort argument in org-ql--query Rather than in the macro. Trying to consolidate. --- org-ql.el | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/org-ql.el b/org-ql.el index ba39ca5..e33634b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -54,18 +54,7 @@ buffer." ,pred-body))) :action-fn ,action-fn :narrow ,narrow - :sort ,(pcase sort - (`(function ,_) - ;; Custom sort function - sort) - ((guard (and sort - (cl-loop for elem in sort - always (memq elem '(date deadline scheduled todo priority))))) - ;; Default sorting functions - (list 'quote sort)) - (_ - ;; Other expression to evaluate - sort)))) + :sort ',sort)) (defmacro org-ql--fmap (fns &rest body) (declare (indent defun) (debug (listp body))) @@ -97,11 +86,18 @@ buffer." (mapcar action-fn (org-ql--filter-buffer :pred pred :narrow narrow))) buffers-or-files)))) - (cl-typecase sort - (list (org-ql--sort-by items sort)) - (function (funcall sort items)) - (null items) - (t (user-error "SORT must be a function or a list of methods (see documentation)"))))) + (pcase sort + (`nil items) + (`(function ,_) + ;; Custom sort function + (funcall sort items)) + ((guard (and sort + (setq sort (-list sort)) + (cl-loop for elem in sort + always (memq elem '(date deadline scheduled todo priority))))) + ;; Default sorting functions + (org-ql--sort-by items sort)) + (_ (user-error "SORT must be either a function, or one or a list of the defined sorting methods (see documentation)"))))) (defun org-ql--sanity-check-form (form) "Signal an error if any of the forms in BODY do not have their preconditions met. From 88cf7f395edd8159bd4babc215cacfa011cbcf9d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 06:42:19 -0500 Subject: [PATCH 099/970] Change: Minor refactoring --- org-ql.el | 62 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/org-ql.el b/org-ql.el index e33634b..c41bbee 100644 --- a/org-ql.el +++ b/org-ql.el @@ -44,14 +44,7 @@ buffer." org-agenda-ng--add-markers ,action-fn))))))) `(org-ql--query ,buffers-or-files - (byte-compile (lambda () - (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda - (= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,pred-body))) + ',pred-body :action-fn ,action-fn :narrow ,narrow :sort ',sort)) @@ -65,27 +58,45 @@ buffer." ;;;; Functions -(cl-defun org-ql--query (buffers-or-files pred &key (action-fn #'identity) narrow sort) +(cl-defun org-ql--query (buffers-or-files pred-body &key (action-fn #'identity) narrow sort) "FIXME: Add docstring." ;; MAYBE: Set :narrow t for buffers and nil for files. (declare (indent defun)) - (let* ((buffers-or-files (cl-typecase buffers-or-files - (null (list (current-buffer))) - (buffer (list buffers-or-files)) - (list buffers-or-files) - (string (list buffers-or-files)))) + (let* ((sources (pcase buffers-or-files + (`nil (list (current-buffer))) + ((pred listp) buffers-or-files) + (_ ; Buffer or string + (list buffers-or-files)))) + (predicate (byte-compile `(lambda () + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,pred-body)))) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) (org-ql--today (org-today)) - (items (-flatten-n 1 (--map (with-current-buffer (cl-typecase it - (buffer it) - (string (or (find-buffer-visiting it) - (find-file-noselect it) - (user-error "Can't open file: %s" it)))) - (mapcar action-fn - (org-ql--filter-buffer :pred pred :narrow narrow))) - buffers-or-files)))) + (items (->> sources + ;; List buffers + (--map (cl-etypecase it + (buffer it) + (string (or (find-buffer-visiting it) + (when (file-readable-p it) + ;; It feels unintuitive that `find-file-noselect' returns + ;; a buffer if the filename doesn't exist. + (find-file-noselect it)) + (user-error "Can't open file: %s" it))))) + ;; Filter buffers (i.e. select items) + (--map (with-current-buffer it + ;; action-fn must be called inside the source buffer. + (mapcar action-fn + (org-ql--select :predicate predicate :narrow narrow)))) + ;; Flatten items + (-flatten-n 1)))) + ;; Sort items (pcase sort (`nil items) (`(function ,_) @@ -116,8 +127,9 @@ Or, when possible, fix the problem." (org-ql--sanity-check-form (cdr elem))) else do (check elem)))) -(cl-defun org-ql--filter-buffer (&key pred narrow) - "Return positions of matching headings in current buffer. +(cl-defun org-ql--select (&key predicate narrow) + ;; FIXME: Docstring + "Return positions of entries in current buffer matching PREDICATE. Headings should return non-nil for any ANY-PREDS and nil for all NONE-PREDS. If NARROW is non-nil, buffer will not be widened first." @@ -143,7 +155,7 @@ first." (goto-char (point-min)) (when (org-before-first-heading-p) (outline-next-heading)) - (cl-loop when (funcall pred) + (cl-loop when (funcall predicate) collect (org-element-headline-parser (line-end-position)) while (outline-next-heading)))))) From 4822f1406f63b78ba42154e26c25a8619a46708b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 07:09:48 -0500 Subject: [PATCH 100/970] Change: Consolidate action --- org-ql.el | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/org-ql.el b/org-ql.el index c41bbee..a3907be 100644 --- a/org-ql.el +++ b/org-ql.el @@ -17,12 +17,14 @@ ;;;; Macros -(cl-defmacro org-ql (buffers-or-files pred-body &key (action-fn '#'identity) - sort narrow markers) +(cl-defmacro org-ql (buffers-or-files pred-body &key sort narrow markers + (action '(org-element-headline-parser (line-end-position)))) "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. -ACTION-FN should take a single argument, which will be the result -of calling `org-element-headline-parser' at each matching entry. +ACTION is a sexp which will be evaluated at each matching entry +with point at the beginning of its heading. It is passed to +`org-ql--query' as a lambda. By default, `org-element-headline-parser' + is called to return an Org element. SORT is a user defined sorting function, or an unquoted list of one or more sorting methods, including: `date', `deadline', @@ -33,19 +35,20 @@ buffer (the default is to widen and search the entire buffer). If MARKERS is non-nil, `org-agenda-ng--add-markers' is used to add markers to each item, pointing to the item in its source -buffer." +buffer. In this case, ACTION should return an Org element." (declare (indent defun)) - (when markers - (setq action-fn (pcase action-fn - (`(function identity) '#'org-agenda-ng--add-markers) - (_ (byte-compile `(lambda (item) - (--> item - ;; Add the markers before calling the action fn - org-agenda-ng--add-markers - ,action-fn))))))) + (setq action (cl-ecase markers + ('t `(lambda () + ;; FIXME: Document that, when markers is t, `action' should return an Org + ;; headline element, which --add-markers works with. On the other hand, + ;; maybe this should be on the agenda-ng side. + (->> ,action + org-agenda-ng--add-markers))) + ('nil `(lambda () + ,action)))) `(org-ql--query ,buffers-or-files ',pred-body - :action-fn ,action-fn + :action ,action :narrow ,narrow :sort ',sort)) @@ -58,7 +61,7 @@ buffer." ;;;; Functions -(cl-defun org-ql--query (buffers-or-files pred-body &key (action-fn #'identity) narrow sort) +(cl-defun org-ql--query (buffers-or-files pred-body &key action narrow sort) "FIXME: Add docstring." ;; MAYBE: Set :narrow t for buffers and nil for files. (declare (indent defun)) @@ -75,6 +78,7 @@ buffer." (<= #'<=) (>= #'>=)) ,pred-body)))) + (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) @@ -91,9 +95,7 @@ buffer." (user-error "Can't open file: %s" it))))) ;; Filter buffers (i.e. select items) (--map (with-current-buffer it - ;; action-fn must be called inside the source buffer. - (mapcar action-fn - (org-ql--select :predicate predicate :narrow narrow)))) + (org-ql--select :predicate predicate :action action :narrow narrow))) ;; Flatten items (-flatten-n 1)))) ;; Sort items @@ -127,11 +129,11 @@ Or, when possible, fix the problem." (org-ql--sanity-check-form (cdr elem))) else do (check elem)))) -(cl-defun org-ql--select (&key predicate narrow) +(cl-defun org-ql--select (&key predicate action narrow) ;; FIXME: Docstring "Return positions of entries in current buffer matching PREDICATE. Headings should return non-nil for any ANY-PREDS and nil for all -NONE-PREDS. If NARROW is non-nil, buffer will not be widened +NONE-PREDS. If NARROW is non-nil, buffer will not be widened first." ;; Cache `org-today' so we don't have to run it repeatedly. (org-ql--fmap ((category #'org-ql--category-p) @@ -156,7 +158,7 @@ first." (when (org-before-first-heading-p) (outline-next-heading)) (cl-loop when (funcall predicate) - collect (org-element-headline-parser (line-end-position)) + collect (funcall action) while (outline-next-heading)))))) ;;;;; Predicates From f6db1097dc6a6325468893d7b38706937de04e1e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 07:34:30 -0500 Subject: [PATCH 101/970] Change: Refactor and tidy Move add-markers function into org-ql, which should help avoid cross-dependency, and should be generally useful. --- org-agenda-ng.el | 26 +++++++-------- org-ql.el | 87 ++++++++++++++++++++++++++++++------------------ 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 2b906fe..eee6e05 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -86,9 +86,7 @@ When nil, buffers are widened before being searched." ;; Call --agenda `(org-agenda-ng--agenda ,files ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. - (byte-compile (lambda () - (cl-symbol-macrolet ((= #'=) (< #'<) (> #'>) (<= #'<=) (>= #'>=)) - ,pred))) + ',pred :sort ',sort)))) ;;;; Functions @@ -96,7 +94,7 @@ When nil, buffers are widened before being searched." ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-agenda-ng--agenda (files pred &key action-fn sort) +(cl-defun org-agenda-ng--agenda (files pred &key sort) ;; `org-ql--query' uses `org-element-headline-parser' by default, which we then map ;; `org-agenda-ng--format-element' across to get formatted, propertized strings for the agenda. ;; NOTE: `org-element-headline-parser' should remain the low-level action function, because the @@ -105,18 +103,18 @@ When nil, buffers are widened before being searched." ;; not find any data to sort on). IOW we have to call `org-agenda-ng--format-element' here, not ;; pass it to lower functions. (declare (indent defun)) - (let* ((entries (mapcar #'org-agenda-ng--format-element - (org-ql--query files - pred - :sort sort - :action-fn #'org-agenda-ng--add-markers))) - (result-string (s-join "\n" entries)) - (target-buffer (get-buffer-create "test-agenda-ng"))) + ;; I think it's reasonable to use `eval' here. + (let* ((entries (->> (eval `(org-ql ',files + ,pred + :sort ,sort + :markers t)) + (mapcar #'org-agenda-ng--format-element) + (s-join "\n"))) + (target-buffer (get-buffer-create "test-agenda-ng")) + (inhibit-read-only t)) (with-current-buffer target-buffer - (read-only-mode -1) (erase-buffer) - (insert result-string) - (read-only-mode 1) + (insert entries) (pop-to-buffer (current-buffer)) (org-agenda-finalize)))) diff --git a/org-ql.el b/org-ql.el index a3907be..bd60866 100644 --- a/org-ql.el +++ b/org-ql.el @@ -43,7 +43,7 @@ buffer. In this case, ACTION should return an Org element." ;; headline element, which --add-markers works with. On the other hand, ;; maybe this should be on the agenda-ng side. (->> ,action - org-agenda-ng--add-markers))) + org-ql--add-agenda-markers))) ('nil `(lambda () ,action)))) `(org-ql--query ,buffers-or-files @@ -61,9 +61,24 @@ buffer. In this case, ACTION should return an Org element." ;;;; Functions -(cl-defun org-ql--query (buffers-or-files pred-body &key action narrow sort) - "FIXME: Add docstring." - ;; MAYBE: Set :narrow t for buffers and nil for files. +(cl-defun org-ql--query (buffers-or-files query &key action narrow sort) + "Return items matching QUERY in BUFFERS-OR-FILES. + +QUERY is an `org-ql' query sexp. + +ACTION is a function which is called on each matching entry, with +point at the beginning of its heading. For example, +`org-element-headline-parser' may be used to parse an entry into +an Org element (note that it must be called with a limit +argument, so a lambda must be used to do so). Also see +`org-ql--add-agenda-markers', which may be used to add markers +compatible with Org Agenda code. + +If NARROW is non-nil, buffers are not widened. + +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', and `priority'." (declare (indent defun)) (let* ((sources (pcase buffers-or-files (`nil (list (current-buffer))) @@ -77,7 +92,7 @@ buffer. In this case, ACTION should return an Org element." (> #'>) (<= #'<=) (>= #'>=)) - ,pred-body)))) + ,query)))) (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) @@ -101,41 +116,17 @@ buffer. In this case, ACTION should return an Org element." ;; Sort items (pcase sort (`nil items) - (`(function ,_) - ;; Custom sort function - (funcall sort items)) ((guard (and sort (setq sort (-list sort)) (cl-loop for elem in sort always (memq elem '(date deadline scheduled todo priority))))) ;; Default sorting functions (org-ql--sort-by items sort)) - (_ (user-error "SORT must be either a function, or one or a list of the defined sorting methods (see documentation)"))))) - -(defun org-ql--sanity-check-form (form) - "Signal an error if any of the forms in BODY do not have their preconditions met. -Or, when possible, fix the problem." - (cl-flet ((check (symbol) - (cl-case symbol - ('done (unless org-done-keywords - ;; NOTE: This check needs to be done from within the Org buffer being checked. - (error "Variable `org-done-keywords' is nil. Are you running this from an Org buffer?"))) - ('habit (unless (featurep 'org-habit) - (require 'org-habit)))))) - (cl-loop for elem in form - if (consp elem) - do (progn - (check (car elem)) - (org-ql--sanity-check-form (cdr elem))) - else do (check elem)))) + (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) (cl-defun org-ql--select (&key predicate action narrow) - ;; FIXME: Docstring - "Return positions of entries in current buffer matching PREDICATE. -Headings should return non-nil for any ANY-PREDS and nil for all -NONE-PREDS. If NARROW is non-nil, buffer will not be widened -first." - ;; Cache `org-today' so we don't have to run it repeatedly. + "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. +If NARROW is non-nil, buffer will not be widened." (org-ql--fmap ((category #'org-ql--category-p) (date #'org-ql--date-plain-p) (deadline #'org-ql--deadline-p) @@ -161,6 +152,38 @@ first." collect (funcall action) while (outline-next-heading)))))) +;;;;; Helpers + +(defun org-ql--add-agenda-markers (element) + "Return ELEMENT with Org Agenda marker text properties added. +ELEMENT should be an Org element like that returned by +`org-element-headline-parser'. This function should be called +from within ELEMENT's buffer. It calls `org-agenda-new-marker', +which see." + (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) + (properties (--> (cadr element) + (plist-put it :org-marker marker) + (plist-put it :org-hd-marker marker)))) + (setf (cadr element) properties) + element)) + +(defun org-ql--sanity-check-form (form) + "Signal an error if any of the forms in BODY do not have their preconditions met. +Or, when possible, fix the problem." + (cl-flet ((check (symbol) + (cl-case symbol + ('done (unless org-done-keywords + ;; NOTE: This check needs to be done from within the Org buffer being checked. + (error "Variable `org-done-keywords' is nil. Are you running this from an Org buffer?"))) + ('habit (unless (featurep 'org-habit) + (require 'org-habit)))))) + (cl-loop for elem in form + if (consp elem) + do (progn + (check (car elem)) + (org-ql--sanity-check-form (cdr elem))) + else do (check elem)))) + ;;;;; Predicates (defun org-ql--category-p (&rest categories) From cdd25e8a7fc53663c8398b4cfe887707498aa717 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 07:41:46 -0500 Subject: [PATCH 102/970] Add: Support org-super-agenda Since we aren't calling org-agenda-finalize-entries anymore, we call org-super-agenda--group-items directly when appropriate. --- org-agenda-ng.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index eee6e05..52f200d 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -104,14 +104,17 @@ When nil, buffers are widened before being searched." ;; pass it to lower functions. (declare (indent defun)) ;; I think it's reasonable to use `eval' here. - (let* ((entries (->> (eval `(org-ql ',files + (let* ((entries (--> (eval `(org-ql ',files ,pred :sort ,sort :markers t)) - (mapcar #'org-agenda-ng--format-element) - (s-join "\n"))) + (mapcar #'org-agenda-ng--format-element it) + (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) + (t it)) + (s-join "\n" it))) (target-buffer (get-buffer-create "test-agenda-ng")) (inhibit-read-only t)) + (with-current-buffer target-buffer (erase-buffer) (insert entries) From c9245be37181d97b93a9745984e7fd8fc2738cad Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 07:48:10 -0500 Subject: [PATCH 103/970] Tidy --- org-agenda-ng.el | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 52f200d..35e0e65 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -42,26 +42,22 @@ ;; FIXME: DRY these two macros. (cl-defmacro org-agenda-ng (&rest args) - "Display an agenda-like buffer of entries in FILES that match PRED. + "Display an agenda-like buffer of entries in FILES that match QUERY. -FILES-OR-PRED is a sexp that is evaluated to get the list of +FILES-OR-QUERY is a sexp that is evaluated to get the list of files to scan. -PRED is a predicate sexp which is evaluated on each entry to test -whether it matches. This should be a form used by `org-ql'. +QUERY is an `org-ql' query. The query may be passed as +FILES-OR-QUERY and QUERY may be left nil, in which case the list +of files will automatically be set to the value of calling +`org-agenda-files'. -The predicate may be passed as FILES-OR-PRED and PRED may be left -nil, in which case the list of files will automatically be set to -the value of calling `org-agenda-files'. - -SORT is a list of sorting keys: `deadline', `scheduled', -`date' (matching either `deadline' or `scheduled'), `priority', -or `todo'. +SORT is passed to `org-ql', which see.. NARROW, when non-nil, means to respect narrowing in buffers. When nil, buffers are widened before being searched." (declare (indent defun) - (advertised-calling-convention '(files-or-pred &optional pred &key sort narrow) nil)) + (advertised-calling-convention (files-or-query &optional query &key sort narrow) nil)) (cl-macrolet ((set-keyword-args (args) `(setq sort (plist-get ,args :sort) narrow (plist-get ,args :narrow)))) @@ -94,18 +90,12 @@ When nil, buffers are widened before being searched." ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-agenda-ng--agenda (files pred &key sort) - ;; `org-ql--query' uses `org-element-headline-parser' by default, which we then map - ;; `org-agenda-ng--format-element' across to get formatted, propertized strings for the agenda. - ;; NOTE: `org-element-headline-parser' should remain the low-level action function, because the - ;; sorting functions work on Org elements (so e.g. if we put `org-agenda-ng--format-element' as - ;; the low-level action function, sorting would do nothing, because the sorting functions would - ;; not find any data to sort on). IOW we have to call `org-agenda-ng--format-element' here, not - ;; pass it to lower functions. +(cl-defun org-agenda-ng--agenda (buffers-files query &key sort) + "FIXME: Docstring" (declare (indent defun)) ;; I think it's reasonable to use `eval' here. - (let* ((entries (--> (eval `(org-ql ',files - ,pred + (let* ((entries (--> (eval `(org-ql ',buffers-files + ,query :sort ,sort :markers t)) (mapcar #'org-agenda-ng--format-element it) @@ -114,7 +104,6 @@ When nil, buffers are widened before being searched." (s-join "\n" it))) (target-buffer (get-buffer-create "test-agenda-ng")) (inhibit-read-only t)) - (with-current-buffer target-buffer (erase-buffer) (insert entries) From 32f2b3304ab96d84a4c4edf7e52f9ba4ade14b61 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 07:49:49 -0500 Subject: [PATCH 104/970] Change: Use macrolet instead of flet for priority sorter --- org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index bd60866..0c43799 100644 --- a/org-ql.el +++ b/org-ql.el @@ -423,8 +423,8 @@ A and B are Org timestamp elements." (defun org-ql--priority< (a b) "Return non-nil if A's priority is higher than B's. A and B are Org headline elements." - (cl-flet ((priority (item) - (org-element-property :priority item))) + (cl-macrolet ((priority (item) + `(org-element-property :priority ,item))) ;; NOTE: Priorities are numbers in Org elements. This might differ from the priority selector logic. (let ((a-priority (priority a)) (b-priority (priority b))) From ad4aad16f174410ccb80d76ae779e342ccc5372f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 08:17:10 -0500 Subject: [PATCH 105/970] Change: Rename fmap macro to flet --- org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 0c43799..46b137d 100644 --- a/org-ql.el +++ b/org-ql.el @@ -52,7 +52,7 @@ buffer. In this case, ACTION should return an Org element." :narrow ,narrow :sort ',sort)) -(defmacro org-ql--fmap (fns &rest body) +(defmacro org-ql--flet (fns &rest body) (declare (indent defun) (debug (listp body))) `(cl-letf ,(cl-loop for (fn target) in fns collect `((symbol-function ',fn) @@ -127,7 +127,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (cl-defun org-ql--select (&key predicate action narrow) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." - (org-ql--fmap ((category #'org-ql--category-p) + (org-ql--flet ((category #'org-ql--category-p) (date #'org-ql--date-plain-p) (deadline #'org-ql--deadline-p) (scheduled #'org-ql--scheduled-p) From 2ddc69b64d38f8637e4be9bc1c59ab9bf04482b6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 20 Aug 2018 08:17:25 -0500 Subject: [PATCH 106/970] Refactor agenda-ng buffer and use org-agenda-mode Using org-agenda-mode isn't exactly *correct*, but since we use some compatible text properties, it does give us some functionality for free, even if it isn't 100% compatible. Note that this should be considered experimental. It's not unimaginable that using some agenda buffer commands in the agenda-ng buffer could have unexpected consequences, including data corruption. However, basic ones like jumping to entries and org-agenda-priority seem to work. --- org-agenda-ng.el | 47 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/org-agenda-ng.el b/org-agenda-ng.el index 35e0e65..e972cc6 100644 --- a/org-agenda-ng.el +++ b/org-agenda-ng.el @@ -37,6 +37,11 @@ (require 'org-ql) +;;;; Variables + +(defvar org-agenda-ng-buffer-name "*Org Agenda NG*" + "Name of default `org-agenda-ng' buffer.") + ;;;; Macros ;; FIXME: DRY these two macros. @@ -45,7 +50,7 @@ "Display an agenda-like buffer of entries in FILES that match QUERY. FILES-OR-QUERY is a sexp that is evaluated to get the list of -files to scan. +buffers and files to scan. QUERY is an `org-ql' query. The query may be passed as FILES-OR-QUERY and QUERY may be left nil, in which case the list @@ -55,14 +60,18 @@ of files will automatically be set to the value of calling SORT is passed to `org-ql', which see.. NARROW, when non-nil, means to respect narrowing in buffers. -When nil, buffers are widened before being searched." +When nil, buffers are widened before being searched. + +BUFFER, when non-nil, is a buffer or buffer name to display the +agenda in, rather than the default." (declare (indent defun) - (advertised-calling-convention (files-or-query &optional query &key sort narrow) nil)) + (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer) nil)) (cl-macrolet ((set-keyword-args (args) `(setq sort (plist-get ,args :sort) - narrow (plist-get ,args :narrow)))) + narrow (plist-get ,args :narrow) + buffer (plist-get ,args :buffer)))) (let ((files '(org-agenda-files)) - pred sort narrow) + query sort narrow buffer) ;; Parse args manually (so we can leave FILES nil for a default argument). ;; TODO: DRY this and org-ql, I think. (pcase args @@ -70,27 +79,28 @@ When nil, buffers are widened before being searched." ;; Files, query, and keyword args (FIXME: Can I combine this and the next one? Does it ;; matter if rest is nil or starts with a keyword?) (setq files arg-files - pred arg-pred) + query arg-pred) (set-keyword-args rest)) (`(,arg-pred . ,(and rest (guard (keywordp (car rest))))) ;; Query and keyword args, no files - (setq pred arg-pred) + (setq query arg-pred) (set-keyword-args rest)) (`(,arg-pred) ;; Only query - (setq pred arg-pred))) + (setq query arg-pred))) ;; Call --agenda `(org-agenda-ng--agenda ,files ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. - ',pred - :sort ',sort)))) + ',query + :sort ',sort + :buffer ,buffer)))) ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-agenda-ng--agenda (buffers-files query &key sort) +(cl-defun org-agenda-ng--agenda (buffers-files query &key sort buffer) "FIXME: Docstring" (declare (indent defun)) ;; I think it's reasonable to use `eval' here. @@ -102,13 +112,22 @@ When nil, buffers are widened before being searched." (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) (t it)) (s-join "\n" it))) - (target-buffer (get-buffer-create "test-agenda-ng")) (inhibit-read-only t)) - (with-current-buffer target-buffer + (with-current-buffer (org-agenda-ng--buffer buffer) (erase-buffer) (insert entries) (pop-to-buffer (current-buffer)) - (org-agenda-finalize)))) + (org-agenda-finalize) + (goto-char (point-min))))) + +(defun org-agenda-ng--buffer (&optional name) + "Return Agenda NG buffer, creating it if necessary. +If NAME is non-nil, return buffer by that name instead of using +default buffer." + (with-current-buffer (get-buffer-create (or name org-agenda-ng-buffer-name)) + (unless (eq major-mode 'org-agenda-mode) + (org-agenda-mode)) + (current-buffer))) (defun org-agenda-ng--format-relative-date (difference) "Return relative date string for DIFFERENCE. From 75886a57a6e80061768879b4d308041fe77a3c05 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 01:01:57 -0500 Subject: [PATCH 107/970] Change: org-agenda-ng -> org-ql-agenda --- README.org | 149 ++++++++++++++------------- examples.org | 25 ++--- notes.org | 4 - org-agenda-ng.el => org-ql-agenda.el | 52 +++++----- 4 files changed, 113 insertions(+), 117 deletions(-) rename org-agenda-ng.el => org-ql-agenda.el (92%) diff --git a/README.org b/README.org index 99dde6e..810ea33 100644 --- a/README.org +++ b/README.org @@ -1,73 +1,28 @@ -* org-agenda-ng / org-ql +* org-ql -This is rudimentary, experimental, proof-of-concept alternative code for generating Org agendas. It doesn't support nearly as many features as =org-agenda.el= does, but it might be useful in some way. It uses some existing code from =org-agenda.el= and tries to be compatible with parts of it, like =org-agenda-finalize-entries= and =org-agenda-finalize=. - -Here's an example of generating a kind of agenda view for today (note that the grouping is provided by [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], not this code: +~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). Some examples: #+BEGIN_SRC elisp - (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" - (and (or (date = today) - (deadline <=) - (scheduled <= today)) - (not (done)))) -#+END_SRC - -[[screenshot.png]] - -Here are some other examples: - -#+BEGIN_SRC elisp - ;; Show an agenda-like view of items in "~/org/main.org" with TODO and SOMEDAY keywords which are - ;; tagged "computer" or "Emacs" and in the category "main": - (org-agenda-ng "~/org/main.org" - (and (todo "TODO" "SOMEDAY") - (tags "computer" "Emacs") - (category "main"))) - - ;; Show an agenda-like view of all habits in all agenda files: - (org-agenda-ng - (habit)) - - ;; Show an agenda-like view similar to a "traditional" Org agenda: - (org-agenda-ng - (or (habit) - (date = today) - (deadline <=) - (scheduled <= today) - (and (todo "DONE" "CANCELLED") - (closed = today)))) -#+END_SRC - -More examples are available in [[examples.org]]. - -** org-ql - -Another way to look at it is like a "query language" for Org buffers. For example: - -#+BEGIN_SRC elisp - ;; Return a list of Org entry elements which have the SOMEDAY keyword, are tagged "Emacs", and have - ;; priority B or higher: + ;; Return a list of Org entry elements in the file "~/org/main.org" which have the SOMEDAY + ;; to-do keyword, are tagged "Emacs", and have priority B or higher. (org-ql "~/org/main.org" (and (todo "SOMEDAY") (tags "Emacs") - (priority >= "B"))) ;; => ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) + (priority >= "B"))) ;=> ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) - ;; Find non-done items which contain the term "Emacs" and have priority "B" or higher, and - ;; return a list of heading positions: - (org-ql org-agenda-files + ;; Return a list of bills coming due, searching all Org Agenda files, sorted by deadline. Deadlines + ;; are compared with configured Org warning days, which is implied by the plain `<=' in the + ;; `deadline' matcher. + (org-ql (org-agenda-files) (and (not (done)) - (regexp "Emacs") - (priority >= "B")) - :action-fn (lambda (element) - (org-element-property :begin element))) ;; => (44154 46469 56008 63965 100008 ...) + (tags "bills") + (deadline <=)) + :sort deadline) - ;; Or you can use mapcar around it to get the same result (API is WIP): - (mapcar (lambda (element) - (org-element-property :begin element)) - (org-ql org-agenda-files - (and (not (done)) - (tags "Emacs") - (priority >= "B")))) ;; => (44154 46469 56008 63965 100008 ...) + ;; Set the tag "Emacs" on every entry in the inbox file that mentions "Emacs". + (org-ql "~/org/inbox.org" + (regexp "Emacs") + :action (org-toggle-tag "Emacs" 'on)) ;; If you kept a database of music in an Org file, you might run a query like this to find tracks ;; composed by Chopin that do not have their key recorded in the database: @@ -77,20 +32,68 @@ Another way to look at it is like a "query language" for Org buffers. For examp (not (property "key")))) #+END_SRC -Instead of opening an agenda-like buffer with matching entries, =org-ql= can take a function as an argument that is called at each matching entry to return a result, and finally it returns a list of the results. For example, you could return a list of positions within the buffer, or a list of headings, or headings with entry contents, etc. By default, the matching element is returned, which is the result of calling =org-element-headline-parser= at that entry. +** org-ql-agenda -Results may also be sorted by a user-defined sorting function, or by some built-in sorters: =date=, =deadline=, =scheduled=, =priority= (which assume that the =action-fn= is the default, =org-element-headline-parser)=. For example: +Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries and present them in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: #+BEGIN_SRC elisp - ;; Return TODO items sorted by deadline, then priority. These built-in sorters assume that items - ;; are Org elements returned by `org-element-headline-parser' (the default action function). - (org-ql "~/org/main.org" - (todo) - :sort (deadline priority)) - - ;; Return TODO items sorted by user-defined sorting function. - (org-ql "~/org/main.org" - (todo) - :sort #'custom-sort-fn) + (org-ql-agenda "~/src/emacs/org-super-agenda/test/test.org" + (and (or (date = today) + (deadline <=) + (scheduled <= today)) + (not (done)))) #+END_SRC +Which presents this buffer: + +[[screenshot.png]] + +*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.) + +Here are some other examples: + +#+BEGIN_SRC elisp + ;; Show an agenda-like view of items in "~/org/main.org" with TODO and SOMEDAY keywords which are + ;; tagged "computer" or "Emacs" and in the category "main": + (org-ql-agenda "~/org/main.org" + (and (todo "TODO" "SOMEDAY") + (tags "computer" "Emacs") + (category "main"))) + + ;; Show an agenda-like view of all habits in all agenda files: + (org-ql-agenda + (habit)) + + ;; Show an agenda-like view similar to a "traditional" Org agenda. + (org-ql-agenda + (or (habit) + (date = today) + (deadline <=) + (scheduled <= today) + (and (todo "DONE" "CANCELLED") + (closed = today)))) +#+END_SRC + +** 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 [[https://orgmode.org/worg/org-tutorials/advanced-searching.html#combining-metadata-and-full-text-queries][advanced searching tutorial]], it would require using ~org-search-view~ with a query with specific regular expression syntax, like this: + +#+BEGIN_EXAMPLE + +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 + +** More examples + +More examples are available in [[examples.org]]. + +** License + +GPLv3 diff --git a/examples.org b/examples.org index 7ac0002..139d4cb 100644 --- a/examples.org +++ b/examples.org @@ -1,20 +1,17 @@ - - * Examples -** Showing TO-READ entries containing the word "lisp" +** Listing bills coming due -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 [[https://orgmode.org/worg/org-tutorials/advanced-searching.html#combining-metadata-and-full-text-queries][advanced searching tutorial]], it would require using ~org-search-view~ with a query with specific regular expression syntax, like this: - -#+BEGIN_EXAMPLE - +lisp +{^\*+\s-+TO-READ\s-} -#+END_EXAMPLE - -But with =org-ql= or =org-agenda-ng=, you would write: +This uses the example in the readme file, but maps across the elements returned by ~org-ql~ to present a simple list of titles and deadlines. #+BEGIN_SRC elisp - (org-agenda-ng - (and (regexp "lisp") - (todo "TO-READ"))) + (--map (list (org-element-property :raw-value it) + (org-timestamp-format (org-element-property :deadline it) "%c")) + (org-ql (org-agenda-files) + (and (not (done)) + (tags "bills") + (deadline <=)) + :sort deadline)) + ;;=> (("Electric bill" "Thu 23 Aug 2018 12:00:00 AM CDT") + ;; ("Rent" "Sat 01 Sep 2018 08:00:00 PM CDT")) #+END_SRC - diff --git a/notes.org b/notes.org index e17bcef..031224b 100644 --- a/notes.org +++ b/notes.org @@ -2,10 +2,6 @@ * Tasks -** TODO Move/rename repo to =org-ql= - -Since =org-sidebar= uses it, it probably makes more sense for =org-ql= to be the primary focus of the repo. But it also uses =org-agenda-ng--format-element=, so =org-agenda-ng= probably should be part of that package, too. - ** TODO Document matchers/selectors/predicates And maybe pick a single name for them... diff --git a/org-agenda-ng.el b/org-ql-agenda.el similarity index 92% rename from org-agenda-ng.el rename to org-ql-agenda.el index e972cc6..9dbbc1d 100644 --- a/org-agenda-ng.el +++ b/org-ql-agenda.el @@ -39,14 +39,14 @@ ;;;; Variables -(defvar org-agenda-ng-buffer-name "*Org Agenda NG*" - "Name of default `org-agenda-ng' buffer.") +(defvar org-ql-agenda-buffer-name "*Org Agenda NG*" + "Name of default `org-ql-agenda' buffer.") ;;;; Macros ;; FIXME: DRY these two macros. -(cl-defmacro org-agenda-ng (&rest args) +(cl-defmacro org-ql-agenda (&rest args) "Display an agenda-like buffer of entries in FILES that match QUERY. FILES-OR-QUERY is a sexp that is evaluated to get the list of @@ -89,7 +89,7 @@ agenda in, rather than the default." ;; Only query (setq query arg-pred))) ;; Call --agenda - `(org-agenda-ng--agenda ,files + `(org-ql-agenda--agenda ,files ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. ',query :sort ',sort @@ -100,7 +100,7 @@ agenda in, rather than the default." ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-agenda-ng--agenda (buffers-files query &key sort buffer) +(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer) "FIXME: Docstring" (declare (indent defun)) ;; I think it's reasonable to use `eval' here. @@ -108,28 +108,28 @@ agenda in, rather than the default." ,query :sort ,sort :markers t)) - (mapcar #'org-agenda-ng--format-element it) + (mapcar #'org-ql-agenda--format-element it) (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) (t it)) (s-join "\n" it))) (inhibit-read-only t)) - (with-current-buffer (org-agenda-ng--buffer buffer) + (with-current-buffer (org-ql-agenda--buffer buffer) (erase-buffer) (insert entries) (pop-to-buffer (current-buffer)) (org-agenda-finalize) (goto-char (point-min))))) -(defun org-agenda-ng--buffer (&optional name) +(defun org-ql-agenda--buffer (&optional name) "Return Agenda NG buffer, creating it if necessary. If NAME is non-nil, return buffer by that name instead of using default buffer." - (with-current-buffer (get-buffer-create (or name org-agenda-ng-buffer-name)) + (with-current-buffer (get-buffer-create (or name org-ql-agenda-buffer-name)) (unless (eq major-mode 'org-agenda-mode) (org-agenda-mode)) (current-buffer))) -(defun org-agenda-ng--format-relative-date (difference) +(defun org-ql-agenda--format-relative-date (difference) "Return relative date string for DIFFERENCE. DIFFERENCE should be an integer number of days, positive for dates in the past, and negative for dates in the future." @@ -141,7 +141,7 @@ dates in the past, and negative for dates in the future." ;;;; Faces/properties -(defun org-agenda-ng--add-markers (element) +(defun org-ql-agenda--add-markers (element) "Return ELEMENT with marker properties added." (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) (properties (--> (cadr element) @@ -150,7 +150,7 @@ dates in the past, and negative for dates in the future." (setf (cadr element) properties) element)) -(defun org-agenda-ng--format-element (element) +(defun org-ql-agenda--format-element (element) ;; This essentially needs to do what `org-agenda-format-item' does, ;; which is a lot. We are a long way from that, but it's a start. "Return ELEMENT as a string with its text-properties set according to its property list. @@ -175,12 +175,12 @@ Its property list should be the second item in the list, as returned by `org-ele ;; --add-deadline-face), and doing it in this form that gets the title hides it even more. ;; Adding the relative due date property should probably be done explicitly and separately ;; (which would also make it easier to do it independently of faces, etc). - (title (--> (org-agenda-ng--add-faces element) + (title (--> (org-ql-agenda--add-faces element) (org-element-property :raw-value it) (org-link-display-format it) )) (todo-keyword (-some--> (org-element-property :todo-keyword element) - (org-agenda-ng--add-todo-face it))) + (org-ql-agenda--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 (if-let ((marker (or (org-element-property :org-hd-marker element) @@ -202,7 +202,7 @@ Its property list should be the second item in the list, as returned by `org-ele (priority-string (-some->> (org-element-property :priority element) (char-to-string) (format "[#%s]") - (org-agenda-ng--add-priority-face))) + (org-ql-agenda--add-priority-face))) (habit-property (org-with-point-at (org-element-property :begin element) (when (org-is-habit-p) (org-habit-parse-todo)))) @@ -220,18 +220,18 @@ Its property list should be the second item in the list, as returned by `org-ele 'tags tag-list 'org-habit-p habit-property)))) -(defun org-agenda-ng--add-faces (element) +(defun org-ql-agenda--add-faces (element) (->> element - (org-agenda-ng--add-scheduled-face) - (org-agenda-ng--add-deadline-face))) + (org-ql-agenda--add-scheduled-face) + (org-ql-agenda--add-deadline-face))) -(defun org-agenda-ng--add-priority-face (string) +(defun org-ql-agenda--add-priority-face (string) "Return STRING with priority face added." (when (string-match "\\(\\[#\\(.\\)\\]\\)" string) (let ((face (org-get-priority-face (string-to-char (match-string 2 string))))) (org-add-props string nil 'face face 'font-lock-fontified t)))) -(defun org-agenda-ng--add-scheduled-face (element) +(defun org-ql-agenda--add-scheduled-face (element) "Add faces to ELEMENT's title for its scheduled status." ;; NOTE: Also adding prefix (if-let ((scheduled-date (org-element-property :scheduled element))) @@ -252,7 +252,7 @@ Its property list should be the second item in the list, as returned by `org-ele (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) (difference-days (- today-day-number scheduled-day-number)) - (relative-due-date (org-add-props (org-agenda-ng--format-relative-date difference-days) nil + (relative-due-date (org-add-props (org-ql-agenda--format-relative-date difference-days) nil 'help-echo (org-element-property :raw-value scheduled-date))) (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) ((< today-day-number scheduled-day-number) scheduled-day-number) @@ -297,7 +297,7 @@ Its property list should be the second item in the list, as returned by `org-ele ;; Not scheduled element)) -(defun org-agenda-ng--add-deadline-face (element) +(defun org-ql-agenda--add-deadline-face (element) "Add faces to ELEMENT's title for its deadline status. Also store relative due date as string in `:relative-due-date' property." @@ -306,7 +306,7 @@ property." (deadline-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter deadline-date 'ignore))) (difference-days (- today-day-number deadline-day-number)) - (relative-due-date (org-add-props (org-agenda-ng--format-relative-date difference-days) nil + (relative-due-date (org-add-props (org-ql-agenda--format-relative-date difference-days) nil 'help-echo (org-element-property :raw-value deadline-date))) (todo-keyword (org-element-property :todo-keyword element)) (done-p (member todo-keyword org-done-keywords)) @@ -327,12 +327,12 @@ property." ;; No deadline element)) -(defun org-agenda-ng--add-todo-face (keyword) +(defun org-ql-agenda--add-todo-face (keyword) (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) ;;;; Footer -(provide 'org-agenda-ng) +(provide 'org-ql-agenda) -;;; org-agenda-ng.el ends here +;;; org-ql-agenda.el ends here From e905105f7eeed731f43d9ddbf1c2ee714f14caf6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 01:13:38 -0500 Subject: [PATCH 108/970] Add example script --- examples.org | 2 ++ examples/org-bills-due.el | 54 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 examples/org-bills-due.el diff --git a/examples.org b/examples.org index 139d4cb..5873c8b 100644 --- a/examples.org +++ b/examples.org @@ -15,3 +15,5 @@ This uses the example in the readme file, but maps across the elements returned ;;=> (("Electric bill" "Thu 23 Aug 2018 12:00:00 AM CDT") ;; ("Rent" "Sat 01 Sep 2018 08:00:00 PM CDT")) #+END_SRC + +This could also be put in a script, which could use desktop notifications to remind of bills coming due: [[examples/org-bills-due.el][org-bills-due.el]]. diff --git a/examples/org-bills-due.el b/examples/org-bills-due.el new file mode 100644 index 0000000..5c7261c --- /dev/null +++ b/examples/org-bills-due.el @@ -0,0 +1,54 @@ +;;; org-bills-due.el + +;;;; Initialize package system + +(require 'package) +(setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/") + ("melpa" . "https://melpa.org/packages/"))) +(package-initialize) + +;; Set load-path, loading org-ql from ~/src/emacs/org-ql (adjust as necessary) +(setq load-path (append (list "~/src/emacs/org-ql" + "~/.emacs.d/load-path") + load-path)) + +;;;; Load packages + +;; Built-in +(require 'cl-lib) +(require 'subr-x) + +(require 'org) +(require 'org-habit) +(require 'org-agenda) + +;; From MELPA +(require 'dash) +(require 'dash-functional) +(require 's) + +;; org-ql +(require 'org-ql) +(require 'org-ql-agenda) + +;;;; Main + +(-if-let* ((header "Bills due within 3 days") + (items (org-ql "~/org/main.org" + (and (deadline <= (+ 3 today)) + (tags "bills")) + :action (org-get-heading 'no-tags 'no-todo))) + (string (concat "
    " + (s-join "" + (--map (concat "
  • " it "
  • ") + items)) + "
"))) + (progn + ;; Send notification + (call-process "notify-send" nil 0 nil + (format "%s" header) + string) + ;; Also output to STDOUT + (princ (format "%s:\n%s" header (s-join "\n" titles)))) + ;; No bills due + (kill-emacs 1)) From 2d0a79a9f399f559ae55ef377e7713de184820cc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 01:32:09 -0500 Subject: [PATCH 109/970] Docs: Mention org-sidebar --- README.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.org b/README.org index 810ea33..ef1b698 100644 --- a/README.org +++ b/README.org @@ -94,6 +94,10 @@ But with ~org-ql-agenda~, you would write: More examples are available in [[examples.org]]. +** org-sidebar + +This package is used by [[https://github.com/alphapapa/org-sidebar][org-sidebar]], which presents a customizable agenda-like view in a sidebar window. + ** License GPLv3 From f9167ccb7aa310fcec747853223978617622ccb7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 02:39:51 -0500 Subject: [PATCH 110/970] Notes: Add note --- notes.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notes.org b/notes.org index 031224b..3f2e0d8 100644 --- a/notes.org +++ b/notes.org @@ -11,6 +11,8 @@ And maybe pick a single name for them... ** TODO 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 Add more sorters? + [ ] =category= From 8716c9a0875f865e08a6d7d0eb331ce22f4b877d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 09:05:52 -0500 Subject: [PATCH 111/970] Fix: (org-ql-agenda) Argument handling Fixes #5. Thanks to @natrys for reporting. --- org-ql-agenda.el | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 9dbbc1d..546a9f6 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -85,6 +85,10 @@ agenda in, rather than the default." ;; Query and keyword args, no files (setq query arg-pred) (set-keyword-args rest)) + (`(,arg-files ,arg-pred) + ;; Files and query, no keywords + (setq files arg-files + query arg-pred)) (`(,arg-pred) ;; Only query (setq query arg-pred))) From d3cb2bfeed1dc5bd91e8a55993cb136426aae045 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 21 Aug 2018 09:10:26 -0500 Subject: [PATCH 112/970] Fix: (org-ql-agenda--add-scheduled-face) todo-keyword error Mentioned in #5. Thanks again to @natrys. --- org-ql-agenda.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 546a9f6..623916d 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -239,7 +239,8 @@ Its property list should be the second item in the list, as returned by `org-ele "Add faces to ELEMENT's title for its scheduled status." ;; NOTE: Also adding prefix (if-let ((scheduled-date (org-element-property :scheduled element))) - (let* ((show-all (or (eq org-agenda-repeating-timestamp-show-all t) + (let* ((todo-keyword (org-element-property :todo-keyword element)) + (show-all (or (eq org-agenda-repeating-timestamp-show-all t) (member todo-keyword org-agenda-repeating-timestamp-show-all))) (raw-value (org-element-property :raw-value scheduled-date)) (sexp-p (string-prefix-p "%%" raw-value)) @@ -273,7 +274,6 @@ Its property list should be the second item in the list, as returned by `org-ele ;; that. (current-buffer) (org-element-property :begin element))))) - (todo-keyword (org-element-property :todo-keyword element)) (face (cond ((member todo-keyword org-done-keywords) 'org-agenda-done) ((= today-day-number scheduled-day-number) 'org-scheduled-today) ((> today-day-number scheduled-day-number) 'org-scheduled-previously) From b4ba9e78fdafe92129d4e56baf1e0629dc357482 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 01:37:08 -0500 Subject: [PATCH 113/970] Fix: (--add-scheduled-face) Remove broken prefix code Also unnecessary since we use --format-relative-date. If we ever want to exactly emulate the Agenda, this can be replaced. See https://github.com/alphapapa/org-ql/issues/5#issuecomment-414717478. --- org-ql-agenda.el | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 623916d..dda1e7a 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -283,19 +283,7 @@ Its property list should be the second item in the list, as returned by `org-ele 'face face))) (properties (--> (cadr element) (plist-put it :title title) - (plist-put it :relative-due-date relative-due-date))) - (prefix (cl-destructuring-bind (first next) org-agenda-scheduled-leaders - (cond ((> scheduled-day-number today-day-number) - ;; Future - first) - ((and (not show-all) - (= repeat today-day-number))) - ((= today-day-number scheduled-day-number) - ;; Today - first) - (t - ;; Subsequent reminders. Count from base schedule. - (format next (1+ (- today-day-number scheduled-day-number)))))))) + (plist-put it :relative-due-date relative-due-date)))) (list (car element) properties)) ;; Not scheduled From cdbe750b7cade6939237277b68a5111009031cfa Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 13:32:44 -0500 Subject: [PATCH 114/970] Fix: Don't treat an element's :begin property as a marker Only markers are markers. Also add FIXME about tag inheritance when no marker is used (although see caveat in it...). --- org-ql-agenda.el | 7 +++++-- org-ql.el | 16 ++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index dda1e7a..4e043cd 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -187,9 +187,12 @@ Its property list should be the second item in the list, as returned by `org-ele (org-ql-agenda--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...) (if-let ((marker (or (org-element-property :org-hd-marker element) - (org-element-property :org-marker element) - (org-element-property :begin element)))) + (org-element-property :org-marker element)))) (with-current-buffer (marker-buffer marker) ;; I wish `org-get-tags-at' used the correct buffer automatically. (org-get-tags-at marker (not org-use-tag-inheritance))) diff --git a/org-ql.el b/org-ql.el index 46b137d..3a26a86 100644 --- a/org-ql.el +++ b/org-ql.el @@ -37,15 +37,15 @@ If MARKERS is non-nil, `org-agenda-ng--add-markers' is used to add markers to each item, pointing to the item in its source buffer. In this case, ACTION should return an Org element." (declare (indent defun)) - (setq action (cl-ecase markers - ('t `(lambda () - ;; FIXME: Document that, when markers is t, `action' should return an Org - ;; headline element, which --add-markers works with. On the other hand, - ;; maybe this should be on the agenda-ng side. - (->> ,action - org-ql--add-agenda-markers))) + (setq action (pcase markers ('nil `(lambda () - ,action)))) + ,action)) + (_ `(lambda () + ;; FIXME: Document that, when markers is t, `action' should return an Org + ;; headline element, which --add-markers works with. On the other hand, + ;; maybe this should be on the agenda-ng side. + (->> ,action + org-ql--add-agenda-markers))))) `(org-ql--query ,buffers-or-files ',pred-body :action ,action From a2d8ed2eeb9978f55fedad26b51356e2c09c2a8f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 13:35:17 -0500 Subject: [PATCH 115/970] Add: Caching Seems to work well so far. Hopefully no bugs will be found (ha, ha)... Fixes #6. Thanks to @yantar92 for suggesting! --- org-ql.el | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 3a26a86..4ef998b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -15,6 +15,13 @@ (defvar org-ql--today nil) +(defvar org-ql-cache (make-hash-table :weakness 'key) + ;; IIUC, setting weakness to `key' means that, when a buffer is closed, its entries will be + ;; removed from this table at the next GC. + "Query cache, keyed by buffer. Each value is a list of the +buffer's modified tick and another hash table, keyed by arguments +passed to `org-ql--select-cached'.") + ;;;; Macros (cl-defmacro org-ql (buffers-or-files pred-body &key sort narrow markers @@ -110,7 +117,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (user-error "Can't open file: %s" it))))) ;; Filter buffers (i.e. select items) (--map (with-current-buffer it - (org-ql--select :predicate predicate :action action :narrow narrow))) + (org-ql--select-cached :predicate predicate :action action :narrow narrow))) ;; Flatten items (-flatten-n 1)))) ;; Sort items @@ -124,6 +131,32 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (org-ql--sort-by items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) +(define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) + (sxhash-equal (prin1-to-string args)))) + +(defun org-ql--select-cached (&rest args) + "Return results for ARGS and current buffer using cache." + ;; MAYBE: Timeout cached queries. Probably not necessarily since they will be removed when a + ;; buffer is closed, or when a query is run after modifying a buffer. + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-cache)) + (query-cache (cadr buffer-cache)) + (modified-tick (car buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cached-result (gethash args query-cache))) + (pcase cached-result + ('org-ql-nil nil) + (_ cached-result)) + (let ((new-result (apply #'org-ql--select args))) + (cond ((or (not query-cache) + (not buffer-unmodified-p)) + (puthash (current-buffer) + (list (buffer-modified-tick) + (aprog1 (make-hash-table :test 'org-ql-hash-test) + (puthash args (or new-result 'org-ql-nil) it))) + org-ql-cache)) + (t (puthash args (or new-result 'org-ql-nil) query-cache))) + new-result))) + (cl-defun org-ql--select (&key predicate action narrow) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." From a9a4ac33d8b85432fe82159ce3ee51333d740c8c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:14:11 -0500 Subject: [PATCH 116/970] Change: Remove org-ql-agenda--add-markers We use org-ql--add-agenda-markers now. --- org-ql-agenda.el | 9 --------- 1 file changed, 9 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 4e043cd..1a9b258 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -145,15 +145,6 @@ dates in the past, and negative for dates in the future." ;;;; Faces/properties -(defun org-ql-agenda--add-markers (element) - "Return ELEMENT with marker properties added." - (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) - (properties (--> (cadr element) - (plist-put it :org-marker marker) - (plist-put it :org-hd-marker marker)))) - (setf (cadr element) properties) - element)) - (defun org-ql-agenda--format-element (element) ;; This essentially needs to do what `org-agenda-format-item' does, ;; which is a lot. We are a long way from that, but it's a start. From 90aa62a5af1b19aced952f73c5ce6f3cfc14c9f0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:15:28 -0500 Subject: [PATCH 117/970] Change/Fix: (org-ql--add-agenda-markers) Rename and use copy-marker org-agenda-new-marker sometimes raises "selecting deleted buffer" errors, and other times returns markers that don't point into a buffer (I don't even know how that's possible). copy-marker always works, so we'll use it, even though it might leave markers hanging around which theoretically could affect performance over time (but isn't Emacs still supposed to GC them? I'm not sure). Also, rename it to org-ql--add-markers, since we're not adding "agenda" markers anymore. --- org-ql.el | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index 4ef998b..19251ac 100644 --- a/org-ql.el +++ b/org-ql.el @@ -52,7 +52,7 @@ buffer. In this case, ACTION should return an Org element." ;; headline element, which --add-markers works with. On the other hand, ;; maybe this should be on the agenda-ng side. (->> ,action - org-ql--add-agenda-markers))))) + org-ql--add-markers))))) `(org-ql--query ,buffers-or-files ',pred-body :action ,action @@ -78,7 +78,7 @@ point at the beginning of its heading. For example, `org-element-headline-parser' may be used to parse an entry into an Org element (note that it must be called with a limit argument, so a lambda must be used to do so). Also see -`org-ql--add-agenda-markers', which may be used to add markers +`org-ql--add-markers', which may be used to add markers compatible with Org Agenda code. If NARROW is non-nil, buffers are not widened. @@ -187,13 +187,16 @@ If NARROW is non-nil, buffer will not be widened." ;;;;; Helpers -(defun org-ql--add-agenda-markers (element) - "Return ELEMENT with Org Agenda marker text properties added. +(defun org-ql--add-markers (element) + "Return ELEMENT with Org marker text properties added. ELEMENT should be an Org element like that returned by `org-element-headline-parser'. This function should be called -from within ELEMENT's buffer. It calls `org-agenda-new-marker', -which see." - (let* ((marker (org-agenda-new-marker (org-element-property :begin element))) +from within ELEMENT's buffer." + ;; FIXME: `org-agenda-new-marker' works, until it doesn't, because...I don't know. It sometimes + ;; raises errors or returns markers that don't point into a buffer. `copy-marker' always works, + ;; of course, but maybe it will leave "dangling" markers, which could affect performance over + ;; time? I don't know, but for now, it seems that we have to use `copy-marker'. + (let* ((marker (copy-marker (org-element-property :begin element))) (properties (--> (cadr element) (plist-put it :org-marker marker) (plist-put it :org-hd-marker marker)))) From e141089633602a762a485ca33374b17c68688c00 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:18:24 -0500 Subject: [PATCH 118/970] Fix: Unused lexical vars --- org-ql.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 19251ac..0ff06a2 100644 --- a/org-ql.el +++ b/org-ql.el @@ -309,9 +309,9 @@ like one returned by `date-to-day'." (org-time-string-to-absolute (org-element-timestamp-interpreter date-element 'ignore)) target-day-number)) - (error "Unknown date-element type: %s" (org-element-property :type date-element))))) - (otherwise (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" - comparator target-date))))) + (_ (error "Unknown date-element type: %s" (org-element-property :type date-element)))))) + (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" + comparator target-date))))) (defsubst org-ql--date-plain-p (&optional comparator target-date) (org-ql--date-p :date comparator target-date)) From 103993c52e2c965287559e95bf5982b119cd2223 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:29:00 -0500 Subject: [PATCH 119/970] Fix: Unused variable warnings We may need these in the future, so rather than have to dig these back out of org-agenda.el, I'll just comment them out for now. This silences the byte-compiler. --- org-ql-agenda.el | 76 +++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 1a9b258..26ff03d 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -162,9 +162,9 @@ Its property list should be the second item in the list, as returned by `org-ele ;; better to avoid this somehow. At least, we should use a ;; function to convert plists to alists, if possible. (properties (cl-loop for (key val) on properties by #'cddr - for key = (intern (cl-subseq (symbol-name key) 1)) - unless (member key '(parent)) - append (list key val))) + for symbol = (intern (cl-subseq (symbol-name key) 1)) + unless (member symbol '(parent)) + append (list symbol val))) ;; TODO: --add-faces is used to add the :relative-due-date property, but that fact is ;; hidden by doing it through --add-faces (which calls --add-scheduled-face and ;; --add-deadline-face), and doing it in this form that gets the title hides it even more. @@ -195,8 +195,7 @@ Its property list should be the second item in the list, as returned by `org-ele (s-join ":" it) (s-wrap it ":") (org-add-props it nil 'face 'org-tag))) - (level (org-element-property :level element)) - (category (org-element-property :category element)) + ;; (category (org-element-property :category element)) (priority-string (-some->> (org-element-property :priority element) (char-to-string) (format "[#%s]") @@ -234,40 +233,45 @@ Its property list should be the second item in the list, as returned by `org-ele ;; NOTE: Also adding prefix (if-let ((scheduled-date (org-element-property :scheduled element))) (let* ((todo-keyword (org-element-property :todo-keyword element)) - (show-all (or (eq org-agenda-repeating-timestamp-show-all t) - (member todo-keyword org-agenda-repeating-timestamp-show-all))) - (raw-value (org-element-property :raw-value scheduled-date)) - (sexp-p (string-prefix-p "%%" raw-value)) (today-day-number (org-today)) - (current-day-number - ;; FIXME: This is supposed to be the, shall we say, - ;; pretend, or perspective, day number that this pass - ;; through the agenda is being made for. We need to - ;; either set this in the calling function, set it here, - ;; or accomplish this in a different way. See - ;; `org-agenda-get-scheduled' and where `date' is set in - ;; `org-agenda-list'. - today-day-number) + ;; (current-day-number + ;; NOTE: Not currently used, but if we ever implement a more "traditional" agenda that + ;; shows perspective of multiple days at once, we'll need this, so I'll leave it for now. + ;; ;; FIXME: This is supposed to be the, shall we say, + ;; ;; pretend, or perspective, day number that this pass + ;; ;; through the agenda is being made for. We need to + ;; ;; either set this in the calling function, set it here, + ;; ;; or accomplish this in a different way. See + ;; ;; `org-agenda-get-scheduled' and where `date' is set in + ;; ;; `org-agenda-list'. + ;; today-day-number) (scheduled-day-number (org-time-string-to-absolute (org-element-timestamp-interpreter scheduled-date 'ignore))) (difference-days (- today-day-number scheduled-day-number)) (relative-due-date (org-add-props (org-ql-agenda--format-relative-date difference-days) nil 'help-echo (org-element-property :raw-value scheduled-date))) - (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) - ((< today-day-number scheduled-day-number) scheduled-day-number) - (t (org-time-string-to-absolute - raw-value - (if show-all - current-day-number - today-day-number) - 'future - ;; FIXME: I don't like - ;; calling `current-buffer' - ;; here. If the element has - ;; a marker, we should use - ;; that. - (current-buffer) - (org-element-property :begin element))))) + ;; FIXME: Unused for now: + ;; (show-all (or (eq org-agenda-repeating-timestamp-show-all t) + ;; (member todo-keyword org-agenda-repeating-timestamp-show-all))) + ;; FIXME: Unused for now: (sexp-p (string-prefix-p "%%" raw-value)) + ;; FIXME: Unused for now: (raw-value (org-element-property :raw-value scheduled-date)) + ;; FIXME: I don't remember what `repeat-day-number' was for, but we aren't using it. + ;; But I'll leave it here for now. + ;; (repeat-day-number (cond (sexp-p (org-time-string-to-absolute scheduled-date)) + ;; ((< today-day-number scheduled-day-number) scheduled-day-number) + ;; (t (org-time-string-to-absolute + ;; raw-value + ;; (if show-all + ;; current-day-number + ;; today-day-number) + ;; 'future + ;; ;; FIXME: I don't like + ;; ;; calling `current-buffer' + ;; ;; here. If the element has + ;; ;; a marker, we should use + ;; ;; that. + ;; (current-buffer) + ;; (org-element-property :begin element))))) (face (cond ((member todo-keyword org-done-keywords) 'org-agenda-done) ((= today-day-number scheduled-day-number) 'org-scheduled-today) ((> today-day-number scheduled-day-number) 'org-scheduled-previously) @@ -294,9 +298,9 @@ property." (difference-days (- today-day-number deadline-day-number)) (relative-due-date (org-add-props (org-ql-agenda--format-relative-date difference-days) nil 'help-echo (org-element-property :raw-value deadline-date))) - (todo-keyword (org-element-property :todo-keyword element)) - (done-p (member todo-keyword org-done-keywords)) - (today-p (= today-day-number deadline-day-number)) + ;; FIXME: Unused for now: (todo-keyword (org-element-property :todo-keyword element)) + ;; FIXME: Unused for now: (done-p (member todo-keyword org-done-keywords)) + ;; FIXME: Unused for now: (today-p (= today-day-number deadline-day-number)) (deadline-passed-fraction (--> (- deadline-day-number today-day-number) (float it) (/ it (max org-deadline-warning-days 1)) From 5774880988d1e01480d61fbd1e65e1354754cd58 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:32:46 -0500 Subject: [PATCH 120/970] Change/Fix: Pass :narrow to org-ql-agenda--agenda This function is not only useful for "agenda" views, in which one would almost surely want a widened buffer, but also agenda-like views of subtrees, in which narrowing should be preserved. --- org-ql-agenda.el | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 26ff03d..491624c 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -97,21 +97,23 @@ agenda in, rather than the default." ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. ',query :sort ',sort - :buffer ,buffer)))) + :buffer ,buffer + :narrow ,narrow)))) ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer) +(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer narrow) "FIXME: Docstring" (declare (indent defun)) ;; I think it's reasonable to use `eval' here. (let* ((entries (--> (eval `(org-ql ',buffers-files ,query :sort ,sort - :markers t)) + :markers t + :narrow ,narrow)) (mapcar #'org-ql-agenda--format-element it) (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) (t it)) From 6a9f5cc37c44c16956de74dfda197b10a2647401 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 14:41:00 -0500 Subject: [PATCH 121/970] Add: Heading matcher This should also be easy to optimize with a buffer-wide regexp search. --- org-ql.el | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org-ql.el b/org-ql.el index 0ff06a2..4edca3f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -172,6 +172,7 @@ If NARROW is non-nil, buffer will not be widened." (tags #'org-ql--tags-p) (property #'org-ql--property-p) (regexp #'org-ql--regexp-p) + (heading #'org-ql--heading-p) (level #'org-ql--level-p) (org-back-to-heading #'outline-back-to-heading)) (save-excursion @@ -378,6 +379,10 @@ comparator, PRIORITY should be a priority string." (goto-char (line-beginning-position)) (re-search-forward regexp end t)))) +(defun org-ql--heading-p (regexp) + "Return non-nil if current entry's heading matches REGEXP." + (string-match regexp (org-get-heading 'no-tags 'no-todo))) + (defun org-ql--property-p (property &optional value) "Return non-nil if current entry has PROPERTY, and optionally VALUE." (pcase property From a3aac8466b5d095306f82b9b0dfb10c9afd046ab Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 16:39:57 -0500 Subject: [PATCH 122/970] Notes: Add task --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 3f2e0d8..3d420ee 100644 --- a/notes.org +++ b/notes.org @@ -2,6 +2,10 @@ * Tasks +** TODO Add ~org-ql-view~ command + +Should work like ~org-sidebar-ql~, but displays an ~org-ql-agenda~ view instead. + ** TODO Document matchers/selectors/predicates And maybe pick a single name for them... From db6543b18c7dbeff93c62bfc7b62cb0c5af5f92d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 16:40:06 -0500 Subject: [PATCH 123/970] Fix: (org-ql--query) Error if run in non-Org-derived buffer --- org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql.el b/org-ql.el index 4edca3f..a54e328 100644 --- a/org-ql.el +++ b/org-ql.el @@ -117,6 +117,8 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (user-error "Can't open file: %s" it))))) ;; Filter buffers (i.e. select items) (--map (with-current-buffer it + (unless (derived-mode-p 'org-mode) + (user-error "Not an Org buffer: %s" (buffer-name))) (org-ql--select-cached :predicate predicate :action action :narrow narrow))) ;; Flatten items (-flatten-n 1)))) From e7bc68c9d103a63311993e0a0559105daa8a834d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 22 Aug 2018 18:13:06 -0500 Subject: [PATCH 124/970] Fix: Don't use aprog1 I wish more people had anaphora installed, but since they don't... --- org-ql.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index a54e328..c2c490c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -153,8 +153,9 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (not buffer-unmodified-p)) (puthash (current-buffer) (list (buffer-modified-tick) - (aprog1 (make-hash-table :test 'org-ql-hash-test) - (puthash args (or new-result 'org-ql-nil) it))) + (let ((table (make-hash-table :test 'org-ql-hash-test))) + (puthash args (or new-result 'org-ql-nil) table) + table)) org-ql-cache)) (t (puthash args (or new-result 'org-ql-nil) query-cache))) new-result))) From bd75b1505603bed0d361d774c6a276c623be5799 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 24 Aug 2018 09:11:12 -0500 Subject: [PATCH 125/970] Docs: Clarify example Show where the grouping comes from, since it's not part of this package. --- README.org | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index ef1b698..14edaa1 100644 --- a/README.org +++ b/README.org @@ -41,7 +41,22 @@ Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries (and (or (date = today) (deadline <=) (scheduled <= today)) - (not (done)))) + (not (done))) + ;; The `org-super-agenda-groups' setting is used automatically when set, or it + ;; may be overriden by specifying it here: + :super-groups '((:name "Bills" + :tag "bills") + (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING") + :order 7) + (:name "Personal" + :habit t + :tag "personal" + :order 3) + (:todo "WAITING" + :order 6) + (:priority "A" :order 1) + (:priority "B" :order 2) + (:priority "C" :order 2))) #+END_SRC Which presents this buffer: From 95958a16a6770da28919847deb5d267c276b8649 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 26 Aug 2018 15:44:50 -0500 Subject: [PATCH 126/970] Notes: Add article --- notes.org | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/notes.org b/notes.org index 3d420ee..2df6df4 100644 --- a/notes.org +++ b/notes.org @@ -190,6 +190,15 @@ Virtually indistinguishable. Going to try moving the =byte-compile= call from t Doesn't seem to make any difference. +* References + +** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] +: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]] + * Examples / testing #+BEGIN_SRC elisp From df5d5e238743193cc060a98c319bd60c77867b5f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 17 Sep 2018 22:25:16 -0500 Subject: [PATCH 127/970] Comment: Add FIXME --- org-ql-agenda.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 491624c..33e6c6f 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -293,6 +293,7 @@ Its property list should be the second item in the list, as returned by `org-ele "Add faces to ELEMENT's title for its deadline status. Also store relative due date as string in `:relative-due-date' property." + ;; FIXME: In my config, doesn't apply orange for approaching deadline the same way the Org Agenda does. (if-let ((deadline-date (org-element-property :deadline element))) (let* ((today-day-number (org-today)) (deadline-day-number (org-time-string-to-absolute From 50fab59fece7a837cd69a396a287f90baf019646 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 19 Nov 2018 03:24:33 -0600 Subject: [PATCH 128/970] Change: Simplify a pcase --- org-ql.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index c2c490c..efe3613 100644 --- a/org-ql.el +++ b/org-ql.el @@ -281,13 +281,13 @@ With COMPARATOR and TARGET-DATE, return non-nil if entry's scheduled date compares with TARGET-DATE according to COMPARATOR. TARGET-DATE may be a string like \"2017-08-05\", or an integer like one returned by `date-to-day'." - (when-let ((timestamp (pcase type - ;; FIXME: Add :date selector, since I put it - ;; in the examples but forgot to actually - ;; make it. - (:deadline (org-entry-get (point) "DEADLINE")) - (:scheduled (org-entry-get (point) "SCHEDULED")) - (:closed (org-entry-get (point) "CLOSED")))) + (when-let (;; FIXME: Add :date selector, since I put it + ;; in the examples but forgot to actually + ;; make it. + (timestamp (org-entry-get (point) (pcase type + (:deadline "DEADLINE") + (:scheduled "SCHEDULED") + (:closed "CLOSED")))) (date-element (with-temp-buffer ;; FIXME: Hack: since we're using ;; (org-element-property :type date-element) From efb6938748e8057a4a4c37b82bf334568c3d9fa8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 14 Dec 2018 23:55:51 -0600 Subject: [PATCH 129/970] Fix: (org-ql-agenda) Restore super-groups functionality Fixes #17. Thanks to Dustin Lacewell (@dustinlacewell). --- org-ql-agenda.el | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 33e6c6f..163351d 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -65,11 +65,12 @@ When nil, buffers are widened before being searched. BUFFER, when non-nil, is a buffer or buffer name to display the agenda in, rather than the default." (declare (indent defun) - (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer) nil)) + (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer super-groups) nil)) (cl-macrolet ((set-keyword-args (args) `(setq sort (plist-get ,args :sort) narrow (plist-get ,args :narrow) - buffer (plist-get ,args :buffer)))) + buffer (plist-get ,args :buffer) + super-groups (plist-get ,args :super-groups)))) (let ((files '(org-agenda-files)) query sort narrow buffer) ;; Parse args manually (so we can leave FILES nil for a default argument). @@ -98,18 +99,20 @@ agenda in, rather than the default." ',query :sort ',sort :buffer ,buffer - :narrow ,narrow)))) + :narrow ,narrow + :super-groups ,super-groups)))) ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer narrow) +(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer narrow super-groups) "FIXME: Docstring" (declare (indent defun)) ;; I think it's reasonable to use `eval' here. - (let* ((entries (--> (eval `(org-ql ',buffers-files + (let* ((org-super-agenda-groups super-groups) + (entries (--> (eval `(org-ql ',buffers-files ,query :sort ,sort :markers t From ed3741de4ba95497e4460694579fb794f2288a33 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 15 Dec 2018 01:03:28 -0600 Subject: [PATCH 130/970] Add: (org-ql-agenda--agenda) org-super-agenda-mode error If groups are specified but the mode isn't active, the user will be confused. We might as well raise an error. --- org-ql-agenda.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 163351d..81d27c9 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -110,6 +110,8 @@ agenda in, rather than the default." (cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer narrow super-groups) "FIXME: Docstring" (declare (indent defun)) + (when (and super-groups (not org-super-agenda-mode)) + (user-error "`org-super-agenda-mode' must be activated to use grouping")) ;; I think it's reasonable to use `eval' here. (let* ((org-super-agenda-groups super-groups) (entries (--> (eval `(org-ql ',buffers-files From a58273c147d236a0892aec68705a4b9cbb277469 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 18 Dec 2018 06:12:16 -0600 Subject: [PATCH 131/970] Fix: Shadowed variable --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 81d27c9..f668f1b 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -72,7 +72,7 @@ agenda in, rather than the default." buffer (plist-get ,args :buffer) super-groups (plist-get ,args :super-groups)))) (let ((files '(org-agenda-files)) - query sort narrow buffer) + query sort narrow buffer super-groups) ;; Parse args manually (so we can leave FILES nil for a default argument). ;; TODO: DRY this and org-ql, I think. (pcase args From 748c3fb619d610a3f71a49c34bedd715e16897f3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 18 Dec 2018 06:16:53 -0600 Subject: [PATCH 132/970] Change: (org-ql-agenda) Allow org-super-agenda-groups global value Also, automatically quote :super-groups in macro expansion, and update example in readme. --- README.org | 26 +++++++++++++------------- org-ql-agenda.el | 10 ++++++++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/README.org b/README.org index 14edaa1..9d66a5a 100644 --- a/README.org +++ b/README.org @@ -44,19 +44,19 @@ Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries (not (done))) ;; The `org-super-agenda-groups' setting is used automatically when set, or it ;; may be overriden by specifying it here: - :super-groups '((:name "Bills" - :tag "bills") - (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING") - :order 7) - (:name "Personal" - :habit t - :tag "personal" - :order 3) - (:todo "WAITING" - :order 6) - (:priority "A" :order 1) - (:priority "B" :order 2) - (:priority "C" :order 2))) + :super-groups ((:name "Bills" + :tag "bills") + (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING") + :order 7) + (:name "Personal" + :habit t + :tag "personal" + :order 3) + (:todo "WAITING" + :order 6) + (:priority "A" :order 1) + (:priority "B" :order 2) + (:priority "C" :order 2))) #+END_SRC Which presents this buffer: diff --git a/org-ql-agenda.el b/org-ql-agenda.el index f668f1b..08553c3 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -63,7 +63,11 @@ NARROW, when non-nil, means to respect narrowing in buffers. When nil, buffers are widened before being searched. BUFFER, when non-nil, is a buffer or buffer name to display the -agenda in, rather than the default." +agenda in, rather than the default. + +SUPER-GROUPS is used to bind variable `org-super-agenda-groups', +which see. If t, the existing value of `org-super-agenda-groups' +is used, rather than binding it locally." (declare (indent defun) (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer super-groups) nil)) (cl-macrolet ((set-keyword-args (args) @@ -93,6 +97,8 @@ agenda in, rather than the default." (`(,arg-pred) ;; Only query (setq query arg-pred))) + (when (eq super-groups t) + (setq super-groups org-super-agenda-groups)) ;; Call --agenda `(org-ql-agenda--agenda ,files ;; TODO: Probably better to just use eval on org-ql rather than reimplementing parts of it here. @@ -100,7 +106,7 @@ agenda in, rather than the default." :sort ',sort :buffer ,buffer :narrow ,narrow - :super-groups ,super-groups)))) + :super-groups ',super-groups)))) ;;;; Functions From 62fa3899014f69d27d22a586c615fddb2773d884 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 28 Dec 2018 10:46:52 -0600 Subject: [PATCH 133/970] Fix: (org-ql) Add package headers --- org-ql.el | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index efe3613..93a1d6b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1,5 +1,17 @@ -;; -*- lexical-binding: t; -*- +;;; org-ql.el --- Query language for Org buffers -*- lexical-binding: t; -*- +;; Author: Adam Porter +;; Url: http://github.com/alphapapa/org-ql +;; Version: 0.1-pre +;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0")) +;; Keywords: hypermedia, outlines, Org, agenda + +;;; Commentary: + +;; `org-ql' is a lispy query language for Org files. It allows you to +;; find Org entries matching certain criteria and perform actions on +;; them, such as collecting their parsed representation with +;; `org-element' (the default action). ;;; Code: From 09501c7f61e8fe9a3afa4ed927408f7b6d8ae824 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 28 Dec 2018 10:49:16 -0600 Subject: [PATCH 134/970] Fix: (org-ql-agenda) Add package headers --- org-ql-agenda.el | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 08553c3..b8c857b 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -1,13 +1,15 @@ -;; -*- lexical-binding: t; -*- +;;; org-ql-agenda.el --- Agenda-like view based on org-ql -*- lexical-binding: t; -*- +;; Author: Adam Porter +;; Url: http://github.com/alphapapa/org-ql +;; Version: 0.1-pre +;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0")) +;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: -;; This is just a proof-of-concept for how the agenda code might be -;; written in a more functional way, to avoid making multiple passes -;; through each file when building a multi-day agenda. - -;; It also functions as a kind of "query language" for Org buffers. +;; This library displays buffers similar to Org Agenda buffers, based +;; on `org-ql' queries. ;;;; Principles @@ -29,14 +31,15 @@ ;;; Code: +(require 'cl-lib) (require 'org) (require 'org-agenda) -(require 'dash) -(require 'cl-lib) (require 'seq) (require 'org-ql) +(require 'dash) + ;;;; Variables (defvar org-ql-agenda-buffer-name "*Org Agenda NG*" From 95a6b9f2d319ce313b21ee1c9e74f9459462366c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 6 Jan 2019 06:57:25 -0600 Subject: [PATCH 135/970] Add: org-ql-search Also move screenshot into subdir. --- README.org | 10 ++++- images/org-ql-search.gif | Bin 0 -> 423732 bytes screenshot.png => images/screenshot.png | Bin org-ql-agenda.el | 55 ++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 images/org-ql-search.gif rename screenshot.png => images/screenshot.png (100%) diff --git a/README.org b/README.org index 9d66a5a..e2fc8fb 100644 --- a/README.org +++ b/README.org @@ -1,3 +1,5 @@ + + * org-ql ~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). Some examples: @@ -32,6 +34,12 @@ (not (property "key")))) #+END_SRC +** org-ql-search + +The command =org-ql-search= prompts for a query, a list of buffers or files, and how to group and sort results. Without prefix, it searches the current buffer instead of prompting. Then it presents the results in an agenda-like view. + +[[images/org-ql-search.gif]] + ** org-ql-agenda Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries and present them in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: @@ -61,7 +69,7 @@ Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries Which presents this buffer: -[[screenshot.png]] +[[images/screenshot.png]] *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.) diff --git a/images/org-ql-search.gif b/images/org-ql-search.gif new file mode 100644 index 0000000000000000000000000000000000000000..fd09ffa2abede867719756feb22f5f2369c58527 GIT binary patch literal 423732 zcmZ?wbhEHbv}5|k`20TuI|G9@3zM|8sFa+7temQnoUE#xvW$X`l!B?WlDvwXv5c~@ zl8Tb9qJpWsyrrCilA4^9nzOvB3y&eYm9m_SmZheepPH7LtagyIs)CuOn!I+Lr>Y{C znUk)bjEk$$WWbW$Wq)Q==Pt{9J5;RA%zZ zaNY8BW&fNqqr9D${nTE1SXvZqTAs|1S18w$ZV*{e)Rf`fmg!iVceA}ec(BJ8WquP@-*nq|5v*LX{TVr@-EL0$csT>aYms_KU3d$}@! z9UDBSq-?Bo)0x#%GmWXgUovXqBL9gOwskP%Pnf#8TRwHl)SqQ?y%P(jO$zXudwx@Q zK;hitf*G5Z_xAKo?OWepc%fg*am}8#WiGcSOI@7k^}9>{#5C{v)#;mOOrE}U%A}=B zv(}yYHC3j3-Nw~xHAD7nS-LKzc;lmu>s_X7O?$GEqh{;LjP0MVE>D`U>BRcgC)Tdp zRCLC??1I?NO%u*<3Yfd~_~dO5Lr>rDI&kRRmN}<)l}PE(+_6bu&Xt& zwkj~GyIg;D_jI{FOSl7TS3@gLU#&fMk+pnxoDB|L2XjobBgt3@&=daQq3p(Q4 z>KPC6cpE=wYo5rO9IRlNd2EA>^Rzj)3a&M0iXOT!RX2Ju6L+3$X4D&xmgvnThL@Ek zkFCx*t;*hhCCLp;|h;AZj9Gy zxp06dgoWYuQ{5bm7H7lh?`Ep$?c>^_9^%&+m>yi-_FS83?TbPO?G-x$1Qs54Xo!`I z5KL*&N#t}n5dJnu>;0ZDc`i4TCm!UAj%60mXv#Xs^4Ytw`>TsYj|N+DCeykjC*H48 z|Mewnnaw59tj6!>(gb<7I~hiZ?p+uxp(36xq>u-%c5-eHk!}b za;EI&+pX_of4|L_@F|k7eJ57+LhHKjEe*c@Yp=gt4sdRH%%Pz5j4P+BRLjXgUFy$< z^!;SpURD&hD_;BXAMpoGwNsK5nz-EF{(SzqO5z4XXiOH%_03`lEJhnn z9y-{OuKdjPh?x43Mco|YdlvOt@LgZ|YR&W?ziuq$FQ~fC=lbDP6}y<^_dC_X2}M)3 zWi+rDhwZ!M5$bWK;LTZ%*6?RD&o{jnnNzgvK&~=NL?Z9J-5DFw=bv-e3y8K9WC{1r zyxl7Pf`KQYS;=IAT|=7bmdZ2gb&S%-6&@Q+(e%-5Tf94{@t7f>vPYJ{j#UXd8yXkv z>|qQ&EYuPB^RSBgKHglpgVo zO;-Cp3rs9+Nz0na@ld2_vds$?Vb-4~>yrvv4Ss#>=XXkWbt%x)XJPIZ7F2QNNZ^X@ z@l?!fnf>|925t|>ls-2yAE zXhRagD@{_0IetnvLfM=OOyXToCsn0V`_$)J;e)3G3)#sTPdX||i_dJ^w z^?BBfGt11jpFEpa^?CLKp5+$DJeV+H@ z-1Y(WG@6+MfL(G=kJdhm^>VoX5MIIjF`Zt+2Xj=dcjKH!dVwug|0A` z?|kVmxFuk!-NRVBTBki$r$Un590VG6oDE*Q%V>qy)m0ph4Ze>{r<)isE;k8%>AO+j znn_P6qhEp(cfqZz>&-%#xKj@~%@+t!IMTrBox3Wo*^}A%iN8Ya-`5OG-U5e|jxYsf z%yLkOV&GiTxF+!jqg$jvn}kc*rUb(S8j4aOTs$T00&_JTckg1>fA@9E!z)@5cT6wX zDT!^GwD%uVs;+eODJ=yyo>Yz4xecuBTg2E6*S-i8JbmHbqHjCy`MmVvd=TAa_HE;o zwYjPK+P4iZnDFQxc$-&!JE}t|V==o^w$DWGd%=1M{Cx(K9L~+Y7qc*YZ){b*8v86Z zt%NOW6PCWq`I>$A_`R|%dvf22K9FKlkoc;Xbu_b5{Ea(jLZ|}YGOZSQ9yzYx0SkFp zo4gaXF26{cwr$4Wd|$>hcTHj*?#?t=6;QM~gl)G)!=>UDo(+>(Bro4M_HNb3p7=A# zWpWApzEUUpo7XrgNN1c_`ex&#>1Up(S^qp4(6?#Ia-XMK(LYZ`oZB>Q`7W8eN^W5jT)$O0>D$W^4awu?={J7a8^wL=I zi%&-RT?PShhEI)rb6?C6Xt>x_cY<-=Lf*^&+Bs$kxGz;dlwRVp`a)&jZ4s3Vae zc`VC&@2sW37Z))}VNIFoa{orYCyiBS_S^M((zmMu2iVFan`GZ43f~qm`f)(# z&zfGv5-A?h1U7w}4?On2Z(cq4akH*UJ4;E2ll@J%I?zxgC*+JTL{ zg=~&8yI&ul$8>b<+uSzgJ?E=}e{@>eW=L$=#W4Av$?f7BSDPq5j|;WF!RpEJ>22^k}vbe$@l;CUHfY? zBk(2HlG#sw2U`4Le3+hCkoow`K9Rr5?{dCwp3nSFJ#TGT(XI4U!)?jzi;~UT8dz^M zs5GWHrKJdZr0_*Fid8g9%xIL_(fB8Y(I+9Bxj>xnsk4b`oZCmnX9avO4+;IgEFj0! zl&;8_mndj)f%k5Jp1Tpx_w52T-+0a(u(AEoEa%7&2DM#kb30*ZW+OM;8a4+(j{7H1u=ESe6 ztcwL1W!TCMjs{p4h`T)O=2#XK9#G^`z^fI(!Cc7OJE6(LndM9dUqy!Kc?t2}83OVN zJci`$P(z2jYi4qR?GSSL9$`*`rUyfokbfNjr5 zX_f>I-6J-a17*F7xUWp)y|z*M!bR3iB8;I;6FePw-!0&N&n$ORz~$*h26G4AFB5o+ z9j5QwWZ|yBctv6QwSuXvj8mK{Cpets*>_?3$Lo`sG^dzZcCm&i1Z6ND6K(SQz_N&y zMRRFL!P9`46t{gVX6`)^&1*1=qmXyQ1%`7c+>UXmDJ3vmZ{TEW(7QOJ$D>*A%8n*G z5rxo)tdkb@t>f%vp1^KYF#GufTV{dTEC#b*1hKL>uoy4v6M4|HD#PZ@zeP@mFL20( ztIqG}H>l*g{h4v!2if@^+!B_v4<8WzdBWzg(?quqwRa1+*b>;1e@u89)ck1D1Oc;V zp@8|{XU;e0VEnO?(cX=TxnM!am9}{nJg+P#*b2{>jhD&n4?${hZVD zU79_C#j~wz+0>TRGepBDsfOHCpS+=x`vY^oh>VVv4toIGNlo*BhpIV`RN{ry#0$8+ z7A@ZR!J^@+IjbV$#Rqe{F7U-HT9VDQq*6%zri1#)57Unc%(#*uSM$jE31_*=ug=@X z6Yfo(_xfgUlRyW{LX)5qOkGQ7b+EE@a%cr}$aQH5EamL^AKbyx*tDV3{cPqE=7zcd zo}|rTd$^n_k#DbO1H&e+tQS4m>YNR;dI}49n{LgSY}F@~zJmSWGRr62_a4`M)0pR6 zu+Zf?$47DTdDAtRJ3Uw$nfET>2oYqQGJ)l;f*zw4D}N+w>?Q89C-WZ|Hvi$2ySrfZ zQ7ZNFt&Z_zwCsa*tH(j;p)2gVKSK!n!K)AKkb9zA|X< zwKaqJ1@r35?cNKxdmT6>q6N|>@ETuUDzJJLYqchK0Cx++#t5ky#~9YG-B8IcxbsWl z!i&Ew5?<>mMhnb~(%jZr|e<-s+)w>q0&Z#@6I^Breb=kJx1f)DWQ zIdH>p!p+K^ucz+R)Dn1+)m6Bedl`q((rT7No8;{O*gn3s>ra(V&Vgyu8`!rb9A?Sh zFsFON$p^c6Zj11F?>S+$@yZ09gVnq3R1V9WUOT^|eVv8Etj{LpjA2eKYxJdQP1jda9 zI_wLV_`F(DvT~K6!P2k^ytWA&=Or+N9pH&!Dqs0pJnVmrJ&YwK`V-9WIvVileN4uQ|x2$xp!Gj$f8yTb`xldl; z3Yo|v_i}~O`c_l!if^0mFZ-tcxt zx8x08-fRZWRZRh{uS(*Ds=Iy zkyjLlu*(CciF58+`-%xLXr77{toe39%<-TXoAVu6jx!JLavI*9;48GS#P1$Q-{0M{ zKGupowiW#Og8RF!;ETJ-TS9o>Iq;mlEAZiLBiFtMpNza_?C|io!1C_wgHvBJmVCJH zmH1FXPe@RJYoftJ){74(26!pWyK7>=#ePmOEvK7J-*jxBcU zgd_yGBIE?a=V?zdc+7P1X?&kRq4P5pMW*Nv5^-0aO8drd#O_R zxUkMMwC}KZoQT{Z4Q9sYMS8*|evgg!y_B_k%zc4vp}~_-LB=+N*A*Muqs*VQ=Lu|i z^?ZFDW9Yt@opOx_dv0@Y>yvq4w*O;sgfII?gNS<}Bvr((>Xg7I=Eq?w#Md=e!r*z5ge`8NeaF z#bAQ~&kP1BcLB$x1|ODjFwReq;ObX8kuWn=j%)tBS85w?nzA$d7QHc{D9_u^-wfQbXwmyfT+9z6AZ_^{3HNooO``hkzX-#ul$@UY^*XS*pZ zD*2z-Hn1;Qz^Q1@K7HP&7CW`5IyR30Hsb<@Hil11`d?J;dmS<*np&OJY#J$1Hw<wPc2>)LAAeV#bs zNlenSL+_rr>;3faV=u`6lF|R{zBre9|F?PXe!j7L#o_rac!KEE`kyoR|J)MKpu7Lm z#4!v7!f=NJl`L&T*PJ`<6c z5TGFEym*(2%7N67{uWVPy$s>5E64PNoLr42q%1lj$Kt}bF=8S^kM|O{vz$8v)0S{c zrj{96a-|;PSg4@r^FlD_M5iYEj4M~tMC82K*%J&nz8sJX5NZ0Q;&t&wnDU7yJPjYb z!ZgV0&CLQbD z{_M>~;~?hFV2_wGML~YfNkZv9|71-MYc$#l^P9|Z{L1n|(vxkKh~&@YX2xL0xi_Q> zHJ^8~KA*rg^`LR~K5fm$O94NPI?wF(WIBG<_=@rZX0AsewpN@gymLQ@$SQnL^!J)9 z9M>)<@%H*w)?W(NK_6|Wu=G5Wnj2rA7ZJ(#OK3*}%Pkq@4GzrwE(VUQ;wc5%x5I*S z7pk3NaB03&)u1@#LCoRByg??C7nCM@JnWm|&hwy2q|IZdj;qZnjmJF9A=L#9tQw4k z`WFnYd}x`R$1>5Gzu2UU&1RN^l8Aunk_(4AjrQ=K5Xg^N#bYD&L-4pjV)8{(fy9hO z3zbbJ4k!oA`q8*TaS4x4OMKJ8CuarUas5kc>AEn9b@KM88(io8zsVdpn{eaCAuV?O z9D_ht@zgDW?y^&jmh16FI4xevv!HR((kVF#Oor*j7Y_4hu09|z{lkR>t(g&f9K1bG ze_6R}3df0(VBbmHzMGhA?q1mwnVFHPc}HWb2)~c%(dOXT(58b|rU#t)svM~(w37Q{ zUX1CMTR|$R8t136>NINAIWC*>tna&o^Fq? z|IccXz)~vgo6yYvPrI?@j!vrg;yW_jiJj`pb|iI6#~x_S)PHs((9J9H@YLTwgch#r zwRW>iof@9DGj+P~=JE@Zb+uln&dxt(nLfAt+0OL&_5awc5}0@l6fzbIO7D8HczW8d zOxJ^dvt5Kv9;swZFVFHZYG-V-Qtek_^vZfNM{Rcw8~3D@t7^8|OgP(BBb>8T&0_0~ zw|88uie4YQ({^fQ^TT`G9~K{2ay#cRe|pYRBd5qLuDyw@zYnZWms_)ZzRtWo>n|S* z)A{@%F8F6?x6X2z!pr{eyU)(KccFkSCq0Wn`Plj`A9wWReJ&}xlTljM7ZyI(M?uK7 zd%+$iJ_|qQo71HxuwC%Hzb9dTiMNH`OMmYQ#2v*;guUob<1*cg=PC`o&%B(w`iLz_Lp?`6RDgYzc7)2RM2q5W9_gUXCo9!3^tgKWM`n5VOpGyTA&i8dxv zni?MQ1%O}n=_@wMW!R~Ttkad4O`!1Pfwx5Ni33O z+2QFe4_WIxq$htV)KGXM(9Oj#vt>eIYtfSAgA1Hg_`-}b&Pnr6Fj1JdxZ;`3WkZM6 zYLEAvmR+jkWO$%(k#mDz)@r4w)xHWx%4avt@tDHv;h(!AX<;p+o0sF4$Ljq5lxDvD z(;yTZ(WGXxV5vvtCjA*A&*bZ!PF)h@>5LNc*L9AZC)sFm%1avFr|z^(4WF52 z5YM@)_z;)STB!xAHzmskbZwe_zoo;$E7P;?Q_sW+r@Qp7s%@RQVx^MklMZ(6Bxz^W zCHWkk92z z+MSv{ZI`k3D{T$$m`%q+HH%DQCS-&NNFARZ^tjwv+9*<<;p= zFPXn&R8X8+EXn(1Qq`V`yrpjHe%%F^I@o!7^K=e}o@n*0-OJMRIibmO{k#;HVuzQ! zZi)ZSSe_6KUVrjc{iey26?-_W3+{R+ysV6PSW#>lV$4^x&5LQ(*(__XnFqt?8=vng z2-+-Mn9R8D^0lyaQ#T1T9xUXLTyQ+_>Q)VBrhgv{SPyMF>62l^Fj?!#Hd#l{>JyuU za`R@Z8Fa4Xj1`qDt-!E5~Hlx8GNSJr>MVN@qW^l9eO1~{dvas)K&y7@ycp? z{Gxh^%F`7UbE2$}&|i zr2X8>yN74<8;jbWzInc$t>m~?L(7wuElbwA79|PEX1JN(y7*5@@IPB|$kBjb7pEU9 zS!TL7)35y2<@s!-D_m`}f~McPvfQn7Rp{QVuCezvj=t+qKy;^J(tb`*yQy@$Si)uNP*iTos=AqUFByMb29c z_n059^kDOpJL>2EEx(9+j*G~K*@t~Mx3sv28r-eRMwARW{rEh1P&KZ31U6t`7@X3XX zg+um_6oM*LtQNY0pKZDu7%YMmx65paP z(w&(scA6HW&7OMu z`G<_N`_1=Flw7h>(InAkpF^;sbfAJzZj$ZKh5z0wZ91A7{QHjsYt#>A(O$!8VMpz* zNE=j(PWkemXW{OvH~pECx@snHU$eV?-lBGMz5~R2G zq|QZO+IP1evj07~@AS{*w{F;TL~iPuvE&-pCOL<17?6R69XH67PYPDP-WRuZ( zdM1~`9Hj$HOV&m@ii#{b^i$ovOIfl>#&2V1<}(PFnp?qxCO z+7ElACiZP9RIuH$qwMx_fiuQJCyY7Q7)B`Z=5q<2lHR%EgTk}l^PgzS`6k$GzT|TL z^0MefY8@K9HB~&t&KsjoE|cx){CI#N{1b1cknToqnQ~{N)vMI=tX!uq-V=GoI(Ugo z!7a530Y{^BRBI!b{w&&_e&|Sq=FvL=M?;d1rsLnucG#`9Ssb)zDu>we6`F53G%qRY?CBOg>7Y94UxVfi4$Y>b zRg0wNRN2g2_^RW2cklBGO&;OZwNo^kbu3>kGFkRYb3((aU5ht1R;^61IWf0s@8^}B z)+(zitT)s;Ej=`QUjGrUt{(Z>4?5O!t_V5J_i@3*OEVe+rYIa1^0+yJhrdCiL1$9h z8Pzq#y(fiFg*`I5c8Yg_laNl9#(GQhlgaJ@3wVznI)2FO6o1vuO}88`a_N7ZV7*>v z|CfN($4{xI1+JZ6)OXK-<3Yxn^A|iPGVvcWTC?>`uhi?^XFR>PNzK_NW4-Cn>2+s% zuT0W8eu(ER!|JVXI5+-Ua#+iL`lZf2YYe5UPs{CCby{cZV~b{^3sd9@1cPVtOtU%A z5g_^Y8qD2c8D#7kFr$e{V`}hAt#eV{p))y;O`f8fu$kda0M}!VCKo>8 zR6%BeK;Ba0y@@K`JdP%pSy&ldrr+>1>*f>Qe6%&lC}bkvW#NgJ3^w1FX1%s^j*Igq z&DR^$7K_T(_89K|H#L8vSe)mylOGIU+%{BrJL|p)|IdqJ65hr-yQgSrE65sd(p3#K z&NVijd`WF>pP;a(Rj`O2dQOo~spSaV--HkA-!a`f-+ zc;Rxzz4eO6)GMA#uS6W7HxZ?O%tPr7nEjY=ym4;wf(p^=mv&#xs+Ckb(%F>I6`i=K=RlCdBqh--r+M8f+-KIPoDnoS z!Y4Z=^z^Q&j0dK4avZ*25b5;EN#>PWlkj2QJ<7IRoX$~84kfP;b~&79*r1W)IOQm( z_Ll3dMNuFXkGCt&X z^(WVKrehJ3y>V;yWE*Z+Y;Y&UW%=Zb-kw)t{&f_nZDF0YEJ!7^kZUPZ=OU#OqIXZY z&WdgC;_CduIV;8UhDX=ZjIOCH{fm{XAGk)mWRVl$T-6+K;+CS&Or_4Jxhrp6^=P>= zQHaN5!V>q^;y9}#F(s=`R-2wY-0RLZ=lHF??pMCfJo!rN>q)`=i&j_uI(?bzOzGVF zj30G&d!0J_$7}KfzV{8@C;!+SoZI)xf&X03{jaX8&m{RYe3997XDO?l`=OBgg-h=H zn)Dyq;+@rkS90%~doJ<}f&yR8O8%O~*LAq_<1W3PD1+Zj zg8y?E9^0(@dZmH+YM-9uROYJ>+15_d{`fF5ab215#J^QSKMMb?V_AIOg-MX(Xz!0z z51*(c{(bUr;_q|+r#!mBsHZ&bLd;!DM&Wa%RqJHqb=Z4d3(q;zR+e)e}UB2jrQS?DSsaytS*GtJ0 zpX6F@e0=e->1Lx@UcolKK^j|A9)vteUwGNEE?9P9ptPv5#?>bYN_Q;mr0i}-L>)^F zvc4Mg>}l}pt8r}462zV*sy$0GdzS3>EG6t&YTC23vS;aS&oZVx%Ut#>YumHzW6yG~ zJe7L z^z&-sR|_LMf#!RM_kT!F)|M09+4AKI&!wJDp+?T|k34&J&SmJiKK)}0 zt}UAww(rHu+Go3rKUf{m$V|H2+b$t>^s}Ykmz@W1t6q~4JCpqMEc5Jp(fbQDS&B4S z_j)iyGzb@2HkE3MZ>XC-#iL>EzUezo@P|uufB(T!)Y-k|S=M^C*A|WaYXus2?3-Sk zD86~w>!OR?TQa8q{V_Sn;Pqa$=?NYE%Wq`v5sq-)ckyJzjVT(U_gQW7dxfqrM`Wy= zSIBDn@8W^1i#y&-xGG(^*RI}n#jVG4=UP4asc84<^40G;*Z*YBUo2=IscOS444Fq3n`!$TUg4y|E5EKs#~W9+*nHyn+sJ~$qW5|44x zxpQk-?BeCRi^W@%I@6A@eu?Nmnwwa>_{ArV2I0pues!3ebV$luyn7SK_+*{?6_t#; z+-;c*|1ugTX||Rq{`<5}qm`*(a{LcgGmnn%6PTTUzS=^GtB zm2iq^^cR(CHn2SCSJfA9V=Ru4=>8|yxYeO(lYu0MN3k-yW$2$H*C*UbY&vGQhowtE z$-HYp(5^e>hn6)KL`(h-lDT->>H96kxwm(OzN_3+QW2$kq+9J$r`r<8Bh4F1yv;pl z8f;rKg<+{gQ)@=Yin$zzKlPL;b1b&jJ6LhtEA7PL&)u^OKh3i2-f|#)`wo6VftkBB ziZ*62beVl(DQHbt(X_qc+rJNAjaWtYRxeHHyd5=_4*G*4~s{(9r5oI?JT z`u-2w_!WNqT;SimqA_8?+$pg_num_WXQx-^<6C@cPp++te<8v@#38Mr)vym zT|0i%_R)TUDHbb*tu{`MKQHW1Im4f!S+`*NzjYH@e;oU?{lRPH4>e{7TKqE@Prc`! zre5~rfUxb#pO@_aik&FhBf)s6FF!?s@tXL|Dc5DRww((sO#X7~(JQYds{-8r@%;Ow zvR+Q|5wqx|_Qy%meUCU-PGI(a{EjF2>6J&Us++&xnz*^x_g;$Lvrp9tuag5l$cC?+ z#{6NzpOXP{zb&3OT~t<@5t8?=P;+{*Ah(hF>oUfU1Q|8~9Sese`Y9*8WF;9GuN{it zB=yDd*t2j0GghGx&m9{WSvvW6CfUr`AaYDlz`#}H#KmOIt`iL^1*)eH9-by5uuUfL zlRBf+6t{<*OIJ3sI4{1}(iD<#fKhLWho$WX6_G$*dv=$Ae^FmDS^_4{6WY=x+J9|{ z_iU*LOsjk}0&K+sW?7Y9;nAx&-1pY&N=EY}NBxOPRZOq09;#rHH!%6SBJwCN$AJQy ztaF!F1h0-edn!~XvZ=&T_FmK_t;F*aJIx~Y-q6dryea+iy4>Gp@9yj>|NQRl@9*ze zSOkwfnVS%5F#kY3mw9B3<(C)C87+s-{5~*m@!plu)8GBA&bv`|aI${>Kbv1)_DW7o zddwv`<({efr1bZ4`+oho@o|det;Oc?jSsiQ*DwAvUB2l;r+H`-uhkEQ7CyBD9Zr(1 z%cKj%-OLkPrCd4Ul7kzKTHAIc2E=x5ZuL0Tp;`B1kt6pcCgon!TNTQE|14kaQ0}+= z^&`2LMIynWibdgKOM`>fPL;{NRzFpyuzh^Gh-HDGi-V9-R;x7cVjjV#m2L`$+b6|o zwD@rI%c%!6Cr#p1n^S0aVs2(h9H+Bz!&A2dLbp!7oICTQ=k{j~_c}MQy0zYOdy%hr z_e#Qo=(#tJ&Yv0;B{ywxfL3a-UfeAC)=aPGFFfvB&RUYYbt;8r zN>3?+>Vk|5S0meduersj-%)tP!}2jpg0V`J)obJBi9)ZL4s6<%p{UL~g+b?F!lVm= z+PYKLE@D#+&^0=EBwSGB^T{usP9J---!k0DI{nsPX+w0L^Sx(vjYrxuU6+DVqUOX&n2DB*>V5U7Hz$q&yIPoJ9@a+Gwf)q)W>@>cwJ%?kIKZ) ze!K02hR>wg9I7&(R>}yik=bUrQbzyu9ljU?_P<#+2bOG>TB{Q4UYPD6RAF+FEtIvz zHAFbwq`-0Bt;ClmS0+eoVArg0unk+rZssO(W#hSHiJB~*106iLa~nC?MW%haw^((i zr-%3q21ADxlDA^tx|D4W;ku)Kw${+mZA&WyKC+{P1&wtMv=ggZx2}|8U+<+967S<&U$^3>N`ty z{sp_XBwYE&^q$)`<%9mxkj5S_0RAzb=VgNqWcz(FUkqYj3Oe2V*j zuu5|T30ejuls_n%yvI#pyotVo8~bC;BptwNUwE#P`% z`fl2ZDNhT$ZZgDbJyGkCVlcIT?og;3Y&p|LRA(cnZ_Zpz-5x#Dp65KpN_=u&UC z5-yb;8o$zn&)e==qrks-!h&r|OdUN8O*IV%jG`wvUC>Qwwyk(szfNQJ8Qw;xq8}PH zHk_B`QeJe4{*-QQa0s4ll>blBw0DtbVAryWm7Dsd|IWyC>$07DC}iH!MX$X5Ro5*$ z_Gz;GFr0R-F<&!|E~NeC?;NHY^fi znsR{*ZzMR_4$gWqch-ZcY8eUqt-N8=94@xR$g1hg$~YtH0mh?Fx5v z4=A+T-rx5;l`V1I={V`zjV&t5(G?1AE~jtrs%zTXsic>8S;g2ar;+KwSzSxh>lTRB5wNI$r#cdBwPd+`O+5I~3{oa2{J^4D`3-3%S+rG6&yE~cx%5~QH?N)43 z4gqbSrn32Xnv`zjj%)cO?rTyeQZUgwQpTCo(^bK1UxjYob#+~x>6&ES*O8ZZUEB6=pXs{dwXb78@4CM4pXr8X z-8YHCyKfw`Gut$I?VD8N-8awGnQd9D`!+Lp_pNLD%(iV_`!=_D_w9TC%yt~seOEYn z_nl{U=DRMh%}e9%^mwi2x%<9uK1=8hh5FjCe6?3An{*Bsb-gK16ycPuz0CF?E-0wM zBPd@=^3VN$^URwjwZ7N;+pf3dz?r?vo7g2&Y;ueo&S-3M`ly|H{QQS?OFDCdP3o90 zJlV8y@?Oqeb6;Ih3-(*Aay4e3^o-fZo_PcbDVrWC{^SwkB7eW@d|_R2$7}YSIB%xR zrcE=Mbgmdq%-{}ObIwFeFpW=Ho*{OZvNWUKQoUjW!8JTiAD$+-hwnN0Z_2H0mn62g z&v7+)-fG0_#zu;)GiodJBIu9@!VM)4rB<&!wV!K1GwN823fAYPTlIf-{-JH?wG@+3SIFgttM<*ZnkFLMC92E)CdsyCbk8Thl# za&1!(6FR2)mMy-5K`7+7kl8|&poJpK5=G+{%Is1UH*=6}Qw(^Kc-`Y{WQecKBHn#d zZ}avX;*W8fcZRVngNbuWOvIg|Nmmx7s2n`_(RIGWA=Qi~MUHEGEsus>;EXR|*R0}Y z$aJ{Rc=X?2#k;(GLE;6CWh!^r@?ym$1ek7eu^A<6Y0de6rAsYgLE6%!zbnpKiUnxM z1Tg(w_}5`Za_Y3qD_u_+Czx$pyg7%<$SH{N3csP>ajQJ#*IVOkxK7yK>e_uaZut-8 z$U8Tu`UDxP#ayaLHuHMqoXg&(%jPocvH7#bR+|>D-SOCd(p(#*xqoz?Sj#P^kj|O;VOJ$!MdE(h8@cy zOdOi#`o<+Z-5@YQ@s;SMyZ4zauJK5y1{SqDK9sarw}kgwiu41t@G`S{D zDc}<*6g%SlRe6m{$nDId1-GP2oo2+jsB>mGly8&cdD1mMHr=K5xofYw%_FsfcPW)& zA=U3>(|_?-$4%kZ@OBoxQeL(+LDa=%YPzwXx<(3vqosPwQ&DCi6-L!5Wls01A4Qg5 zQg@sByte63oNh?{x%9eS={x@g9=g1dgR{g-A(f$Y+g;8j8l`Sxi82$COAl_)5U{
+u>_7Tg> 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 mhzkw+Q+7&)agkD1vFfTt>=Lh)-ib@*)jAs| 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

{1i# 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"Zkme@4` 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.?yh7#38U2o=ch1dT;VHv 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

4@y<27K7W!|G)VGM)NbdVyi9{f zWP_QIfz_Htl8^qJYPO#GxXbd*A`jseonnu=&%aRHC2Y_0vgMTHnv8>oS*2tiy6q^} z;W?#Rq8DVmqP-NiNQ1CyuEx^Mu)iC@}I0E>+ncQ+(dF+*9kk zQ06W@xlJducW~)sFPvm^AXw>N`DBX~J7;XOKBKMr?d|ksZ4*{}S#Fa0VHLN;rHviF zQadC!o6QNE!8di^sj3;fp71@^N*4WcL|k@)YEVUTyQ0|^)s1|!-!1Ag%R;tO}pG$BJX>hn+lEn>nv@ z{84D~S+OF|%=;QcTk^lo=W~1ZELtv`=QGb}RfUwLPthse^qgJw7SmVmZGI#erFm#^ z(D7?0wU57#?|4_tSbX;4%AMbLoDMbI{-9oc-@l5-{qFzFm}Zw~ZGSeoectwa*=_$^ zU#~xISN(ST^L^Ft_p{&s_2Rht{+hef-t+eET&8@^?Ca&6`!zpz&WgMAGyZH9*S6%% zO8@`9XHQ^Y^|1N!aap0ruCt8KO%MF!Jz+* K6SH|Z7_0$5ceXMB literal 0 HcmV?d00001 diff --git a/screenshot.png b/images/screenshot.png similarity index 100% rename from screenshot.png rename to images/screenshot.png diff --git a/org-ql-agenda.el b/org-ql-agenda.el index b8c857b..d12636f 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -111,6 +111,61 @@ is used, rather than binding it locally." :narrow ,narrow :super-groups ',super-groups)))) +;;;; Commands + +;; TODO: This is called `org-ql-search' but it's in org-ql-agenda.el because +;; it uses `org-ql-agenda--agenda'. Maybe this could be better organized. + +;;;###autoload +(defun org-ql-search (query &optional buffers-files narrow group sort) + "Read QUERY and search with `org-ql'. +Interactively, prompt for these variables: + +BUFFERS-FILES: A list of buffers and/or files to search, or an +expression which evaluates to such a list. + +GROUP: An `org-super-agenda' auto-grouping selector. See +variable `org-super-agenda-auto-selector-keywords'. + +NARROW: Don't widen buffers before searching. Buffers are +widened by default. With prefix, leave narrowed. + +SORT: One or a list of `org-ql' sorting functions, like `date' or +`priority'." + (interactive (progn + (when (and current-prefix-arg + (not (derived-mode-p 'org-mode))) + (user-error "Not an Org buffer: %s" (buffer-name))) + (list (read-minibuffer "Query: ") + (--if-let (read-from-minibuffer "Buffers/Files (blank for current buffer): ") + ;; TODO: Add glob matching? Buffer mode matching? + (pcase it + ("" (current-buffer)) + ((rx bos "(") (-flatten (eval (read it)))) + (_ (s-split (rx (1+ space)) it))) + (current-buffer)) + (eq current-prefix-arg '(4)) + (pcase (completing-read "Group by: " + (cons "Don't group" + (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + ("Don't group" nil) + (property (list (list (intern (concat ":auto-" property)))))) + (pcase (completing-read "Sort by: " + (list "Don't sort" + "date" + "deadline" + "priority" + "scheduled" + "todo")) + ("Don't sort" nil) + (sort (intern sort)))))) + (org-ql-agenda--agenda buffers-files + query + :narrow narrow + :sort sort + :super-groups group)) + ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the From f2be12acf8d51ca6e764035011b7c095353a542f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 14 Jan 2019 17:37:20 -0600 Subject: [PATCH 136/970] Notes: Update notes --- notes.org | 104 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 41 deletions(-) diff --git a/notes.org b/notes.org index 2df6df4..976be1a 100644 --- a/notes.org +++ b/notes.org @@ -2,42 +2,28 @@ * Tasks -** TODO Add ~org-ql-view~ command +** TODO [#A] Tools for saving queries and accessing them -Should work like ~org-sidebar-ql~, but displays an ~org-ql-agenda~ view instead. +*** TODO Save query from ql-agenda buffer -** TODO Document matchers/selectors/predicates +*** TODO Access saved query from saved query list -And maybe pick a single name for them... +*** TODO Org link types -+ =deadline= :: Be sure to explain how it works with regard to the implied date and =today=. -+ =date=, =scheduled= :: No implied date, but supports =today=. +This would be useful for having a menu of saved queries as Org links, or even bookmarking saved queries. -** TODO Document sorters +**** TODO For all parameters -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 For saved queries -** TODO Add more sorters? +*** TODO Bookmarks -+ [ ] =category= -+ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry +** UNDERWAY [#B] Dual matching with regexp and predicates +:PROPERTIES: +:ID: 39972bb5-fdd0-4754-93ba-c85796a67ccf +:END: -** MAYBE Date predicate that searches entire entry - -Because the existing ones only search the special date property line. - -** TODO 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 -* Ideas - -** SOMEDAY Dual matching with regexp and predicates +/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. @@ -53,25 +39,37 @@ Only entries that contain the word =lisp= can be matches, and searching each ent 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. -** 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: +** TODO [#A] Publish to MELPA -[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. +** TODO Add more sorters? -[2018-05-10 Thu 15:01] I already changed to using buffer-parsing predicates instead of =org-element-parse-buffer=. ++ [ ] =category= ++ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry -** DONE Use macros for =date= -CLOSED: [2018-05-10 Thu 14:59] -:LOGBOOK: -- State "DONE" from [2018-05-10 Thu 14:59] -:END: +** TODO Document matchers/selectors/predicates -If I made the =date= selector a macro, I could avoid the need to quote the comparator. +And maybe pick a single name for them... -Also, maybe instead of having a single =date= selector, I should have =scheduled=, =deadline=, etc. ++ =deadline= :: Be sure to explain how it works with regard to the implied date and =today=. ++ =date=, =scheduled= :: No implied date, but supports =today=. + +** TODO 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 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 + +** MAYBE Date predicate that searches entire entry + +Because the existing ones only search the special date property line. ** DONE Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] @@ -190,6 +188,26 @@ Virtually indistinguishable. Going to try moving the =byte-compile= call from t Doesn't seem to make any difference. +** 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. + * References ** [[https://m00natic.github.io/lisp/manual-jit.html][Uniform Structured Syntax, Metaprogramming and Run-time Compilation]] @@ -586,6 +604,7 @@ outline-on-heading-p 3452 0.0101 string-match 4594 0.0064121759 1.395...e-06 mapcar 30 0.0041008740 0.0001366958 #+end_example + ** Profiling position-based *** Macro @@ -705,6 +724,7 @@ org-back-to-heading 725 0.0037 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: @@ -932,6 +952,7 @@ org-super-agenda--filter-finalize-entries 5 0.1316 ** Profiling tags matching *** ng + #+BEGIN_SRC elisp (elp-profile 1 nil (org-agenda-ng "~/org/main.org" @@ -963,6 +984,7 @@ org-super-agenda--filter-finalize-entries 5 0.1316 | 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" From 20d563452fe705cc3d3e4e0281b8dfb49f1cd160 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 14 Jan 2019 18:31:37 -0600 Subject: [PATCH 137/970] Change: (org-ql-search) Switch to keyword arguments And order arguments like other org-ql functions. Note that the code shown in the animation in the readme doesn't reflect this change. --- org-ql-agenda.el | 53 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index d12636f..27e2b48 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -117,18 +117,19 @@ is used, rather than binding it locally." ;; it uses `org-ql-agenda--agenda'. Maybe this could be better organized. ;;;###autoload -(defun org-ql-search (query &optional buffers-files narrow group sort) +(cl-defun org-ql-search (buffers-files query &key narrow groups sort) "Read QUERY and search with `org-ql'. Interactively, prompt for these variables: -BUFFERS-FILES: A list of buffers and/or files to search, or an -expression which evaluates to such a list. +BUFFERS-FILES: A list of buffers and/or files to search. +Interactively, may also be an expression which evaluates to such +a list. -GROUP: An `org-super-agenda' auto-grouping selector. See -variable `org-super-agenda-auto-selector-keywords'. +GROUPS: An `org-super-agenda' group set. See variable +`org-super-agenda-groups'. -NARROW: Don't widen buffers before searching. Buffers are -widened by default. With prefix, leave narrowed. +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'." @@ -136,35 +137,35 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (when (and current-prefix-arg (not (derived-mode-p 'org-mode))) (user-error "Not an Org buffer: %s" (buffer-name))) - (list (read-minibuffer "Query: ") - (--if-let (read-from-minibuffer "Buffers/Files (blank for current buffer): ") + (list (--if-let (read-from-minibuffer "Buffers/Files (blank for current buffer): ") ;; TODO: Add glob matching? Buffer mode matching? (pcase it ("" (current-buffer)) ((rx bos "(") (-flatten (eval (read it)))) (_ (s-split (rx (1+ space)) it))) (current-buffer)) - (eq current-prefix-arg '(4)) - (pcase (completing-read "Group by: " - (cons "Don't group" - (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6)))) - ("Don't group" nil) - (property (list (list (intern (concat ":auto-" property)))))) - (pcase (completing-read "Sort by: " - (list "Don't sort" - "date" - "deadline" - "priority" - "scheduled" - "todo")) - ("Don't sort" nil) - (sort (intern sort)))))) + (read-minibuffer "Query: ") + :narrow (eq current-prefix-arg '(4)) + :groups (pcase (completing-read "Group by: " + (cons "Don't group" + (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + ("Don't group" nil) + (property (list (list (intern (concat ":auto-" property)))))) + :sort (pcase (completing-read "Sort by: " + (list "Don't sort" + "date" + "deadline" + "priority" + "scheduled" + "todo")) + ("Don't sort" nil) + (sort (intern sort)))))) (org-ql-agenda--agenda buffers-files query :narrow narrow :sort sort - :super-groups group)) + :super-groups groups)) ;;;; Functions From 588ee2cb12c7617bc8f7f010183e092975d97f67 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 14 Jan 2019 18:36:14 -0600 Subject: [PATCH 138/970] Change: (org-ql-search) Declare indent --- org-ql-agenda.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 27e2b48..5cc58a5 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -133,6 +133,7 @@ searching. Interactively, with prefix, leave narrowed. SORT: One or a list of `org-ql' sorting functions, like `date' or `priority'." + (declare (indent defun)) (interactive (progn (when (and current-prefix-arg (not (derived-mode-p 'org-mode))) From 50465f0af801b4e1704e6e28f61ab5406ea72a5a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 14 Jan 2019 18:38:59 -0600 Subject: [PATCH 139/970] Docs: Add org-ql-search snippet example --- README.org | 4 ++++ images/org-ql-search-snippet.png | Bin 0 -> 88515 bytes 2 files changed, 4 insertions(+) create mode 100644 images/org-ql-search-snippet.png diff --git a/README.org b/README.org index e2fc8fb..8b799bd 100644 --- a/README.org +++ b/README.org @@ -40,6 +40,10 @@ The command =org-ql-search= prompts for a query, a list of buffers or files, and [[images/org-ql-search.gif]] +Here's an example of using it to generate an agenda-like view for certain files in a directory tree: + +[[images/org-ql-search-snippet.png]] + ** org-ql-agenda Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries and present them in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: diff --git a/images/org-ql-search-snippet.png b/images/org-ql-search-snippet.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb7398f21d64f498efb9ee936655ad98ed765e8 GIT binary patch literal 88515 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

o^|wRxqdbOjhB%^*Z0S zcHwW`E2SPTnr>R_k6y^-T(niaV5eGJ)pVB)+I?F35=B}+52vsH_-dQ?pP$S87X4bj zN_g_CgDo>(FW%AksV~zuM(_Ki{V9sU&DVEcuq-;c$m+Fbsmg{W8m$_hie|ezZU(-M z$?3e4&1$_qSkNaqGEqkDNJkE=bdtdS{UIq4Pl za%I<{;?K!1KAvUt$i1eS5q2koW6(5A(%-uFze- z?B4uBch2IhbjkUlYaYE6-@ftI+v9gHdhJa=AQH-defOoxpRYfAPO8$dENgf?F>k?} z=zWj;`xB#f&iMapZH7-(!@6f#d~eoEx^|bygg&>l&D6aA^KayeeQtJD<@VEU1*ct_ zaq60QnDNzB35L=W%<4P;Buu!aJpV(O>ym9AH;lS&Y)cb0Wb0h8dgf$y{y^n*@t`7p z(hMv6r1>8{%@R$FPyPEMB{Ad48r$>RmwlO6y~5gH^89$C-kSR^EXxW*|2+MiyEk2V zR?*M)^2slE^1Dx-WZHf`Zl>>F_uDt`7ygfvQH(79d2DsC#n;>Zmhbnmb7y%ZzFvJg z(Ej%XS=~pipfx)DyVakBUNiDlSO2{Dvz5ZbxBE6fVpOe9rYvXeXg&MRzNKC#MN<*C2Y$--u<^%l?dIGPlCHZ@epG;OZ24V(4u z(HE2bGoSsgoOE=;q0Q^_lKL*4`4=l%a_6(ThIhmywU3{snYx^ox_9pNo8N!9-aa~e zwn>45Y4MJh!rgM~po@p@`0_u|BD^M%<$s%7P|6Hz4 zEwRnoE~DX@Q;pc1j&aFOB*t55^`p1$&hdJdv6Q$p(Zi!sBA@y1O z=A&j0avGi+rCU{d_}w|M{dxWLt6`FE#&Ilv3-4{+TX=7KoP442IqOC-Z*x{NHD;^|Szk~jZaYG3u7I9)J1 zms2`*-}>20^?7&Lr20HQ8ZLhM=gH%5Uib0uUia5ZA@aoBtsT0?n>`J)cidWa^XpAR zJqzB%@9aO#uHT&Ny8N_?U(~t!O11Wso$Zqzv;TZh#9rm~=llC7&t#j<+L=e`>6nnA)rfw`~8WTk?Dp3Az&2 zx3ly~!R4IYVs>mXM#fLel$NO$Kgr0l?7FihukPcu^@YpyA6dWtt+eIu!$n8=-Q(=S zThiU%m(Tg0du$cE(pmjWMkR62Cp*uqss0+{b$`FdnNvGerqrF=?aRpYOJiE%n%vGU zZ+4k}YB{_%oBxP!)XC|~D{p?im~VM~Ws?7Swb)4=JM8bgv)VoRMaj)mKYpnF``X+5 zMdjRs@AKmhPWts$relkIuSKBoWV5`-OJ%s(_BKD7TfIZ*W$yBxq-xHc@^2r`F~4KC zt-W~NiO*B^T>p9Yw`xvhsbFBW{gdOJuYaCeQo*;Sr2T*2pO*jk-e=6^>}L{uUc3MC z9`~*-e3pIlms#-_K3-%vYjefZ)#o?aooukQ>s_&q?N*cEvXyRqjQj6)yzF@V(r%Sr z$R(Kz1*W0F%fGp0wD*gtfBNLQWB%KH$1Crrt*KI(INkAhXz?We?8`s@-`xHFgT=bv z|GvM!+2{IxszT=>zYX2Ki(Doy;!+LVq~f(mXXl?B^}fePI^SCCpBGkUyg+j-# zZ+d*AP~>!1mA;6oSm2vU9$lg;jFU209KOURY^*JR_K&fF<@7l{vDUZ0tK@9^J8sUj ze17K4xto^8pCf-Ch`lp4;OOe#RwcW$p?YDLRjqL#(+R7~l3$su^lrF+>mrwX=n zX0yCD*gIJlZP_6>J?`(86RDEFE#7Nvd^PcwkNXy@6|?65O5XZo`S~T~w>^(NVQf@% zoB6%-!ZkPPm(vVvZKqrMJ+_i_Gqj53e)Q@4^dRnwuR}MgMHyUJz5ni4ajz5ammYur z^uqG_LHpjBi9MHjwDs8!zaFHwvWia8<#u!3E_93Wzqq3B^JG&@r$zqVh|;-c-COppFnn;#WZFG5&hMR8Litf= z*0kx$?9kxREt37hyYgL^SA=oFJEp#*LrGnUdlTi)HB7t|qRrMMKIcf1m7HGixxj9} za2=KT-BZjbPFe7voIQXsG=KMTFJ@llZ8NGjPG7nET%pLdnPTs~Q+N&Y7N5Ro8+OFh z|Iwb~7U!(9mY50@l|S^&yL&=7ARf&BWOGKAhSXyQj#eb9b1J+TjKJ&s3aV zr2S^`+1y16=7P#xo~=uJ`s-3iPIOtW zopvhiyX&djMQWQZ7EeFrmVf`GdEeVSpP45%&3vrkvoX=zBk|IlpFZa00XIcYpZ{?B zdhC0POS8q+N9^0I6s~wL*)@h+{o<2}w7mDV-}q^nB%t$*}z`Mx8{55w+N{A1?Z zQN8kgK;*nj4wKI}FE(sBSvGB2gWC!D+?f-T4m|Fiac!pm`#o!=b>()}?K)<4PP#)o zEVjIM;_HO7b59=*w#}*9E7iX0;f?)s&&%!VZcpF#;f$jC!X2*#j@QhZ{&>Dj^1ayA zKTn^$yJc(H1*za2v)VrYIKF4XhL)@RYaTmxcP(E$?Yq5=@ZpaJU(BS#N_M?kdT!$B z#qs-A{@3hT`^HW@M*Mu4`GmlI9jV^J8?_#k&r5vHzS~mfY1^@k(*7Emm%iQp7H#j> zoOom#c4X@Vwv&f;)IHksxO8dKf%V~+=9#PAeCMp5TlROCV_a(O-XoRAvvraWl=T4#O1lGXiV{ zSC3c58y+*si?0@sydD2|>ax}Eb@i{ip4lnj6qBxUZuk9&qm{Ea=RdOM_jk7b!e@W~ zuB*pJxGas{5lozfW6F zE4(K)A({6#Fnb`E3e;s_}sh-<%zsc&O{y!f0i;S9mP^r}lMezf0ZCeG-{}4`x>NOk8&L!RZT~LD!;}@tovPTxTfs-1b@FJqEi~ ze7hq}H+MYw_3U%~wQh~F)J;WKd3@UMJ#KfeIvHQUAHVs)#C=Xj#5;XvY-5)GvHbAg z?+!eAivrcfZnXQAY(6)$KxCR^kGWBVxl{Fn(EHOnx5&--Uv&A)EAtP}9QUSjDIPI} z_-=Ro-g}#mTh6qZ+T}Qt*KKY`lJ_qbwV6>j3iot3NIf`nF?kO6=Wb)6NdGGl4=j>4 zxhK#3=*H&W%gFvkd9D6jF~1&FFU!6eIf^YixIE{4k2qe*&r$Z_rlxZC@?{j#$& z9#zX`nilYW=Wnws3)s&)L?z9cc%tfyQuE?tDehhOcj+5hWVM*RaF2>ln^pJs z&&BDQEdtjCIzP)jws`;f&=&di$LjxwbRDWq_uSi&6ufPEgJvg-vH)B2&Az)A%;Wb! z%nQx=WehR!;U>f90`VyYS1d9Vg65Pj$^7-TJ9VZLN8#HE7Vi!FKFjI6S@rbtJQ=M^ zzuFAHD0MmaS*>!eyklg^+nuzq;Fby3uif<@-IQKW%N0p#Y~Ow6^wBxYg|2M;`fPtb zxh+21BJe0n6}<<-&n7S?QmbCEHXT|NG}{l09$eRufjP3mvLT zHcmPP8ttb1_s@M{Q8ru6nff*Al#`-V*}l`!Ur%5zn3`pEG^b#UmHS zQz7$J*s0_78Qw{)g@2D$YI6$zytOOyP3^~8zN#lIsuK@7aTspPn-Cru&tG_tZPI6M zkGGcIli4?&S~lUSmGfeMD}EtKofd)Q_iQg6V)zU1acx_pX;b!|YZ9-PoxAMp?J|o$ zyVX}Nabe?DJR(|nmnZSX#1;99Edog?o^!SfIB_Vpy=jv?)bT2->sQzrk#mvfgt@sq zmQDA+U)B9RN_oGer~bQNvw9D06Z!Z={CV*2U)FElOe^G6Y}s+ECy4#fnIoS6PoDQK z3XuJOEZqLKtJlr-KU_2QEb0%2+ue1Vo|b&;%>9p#52bvtIY0khO{;N~Sh>y*-TGM< z4|!YvpCew~tg$Te&(BT&+n?qp%XV`=>|ma!}o#N9$*l z1$s*P{SnOO5d5lpIo$EecZQ=;2Toa**;PKZ+;;qfAM@TF*`0^PoHz`n+-f-vPuSEV zRLo|)saStb!kP3sx1#uMTmPypi{e>Ox?%AzW-HAn`z~=!GMo_mfn|Htf@R-C`@Vf= zs=5{TeCMn1pEqWoeKYC($Ky9oKEL1W;c*ML7Qj!!>R{ipvpIQp&OAHDn^RtyRQ2dl zR_8Ca03A=2%)MK7JndvsY!L`w9w>L{#Z#XhEv}iyC%sE9ig+#CP~UaXXmTZ|)KydY zNkN+?9bMU(^J(XY()}k-_wD{U`Hy-;++)@4DMoD%%I0O;cxx=pzt{Ked*x#v_ONuu z?z||kz#=KP;|H|NKb^U#Tf%D>Utn^8#+ctgf`#tBET@!fLQ5vv8{7ll@Q(Rte6=$u=Hsq-?pPu(+n}Ab? zq4}wBg(%BA$!U%!o2Rhy1=s3rIOLG^OQ|dK$>eEsWjJTdm}9Cei4ocrQFBd>31 zS5@Hs%pV5DDaTp9SvcfsKiK+p^38&4=Y2(|_y4jBzfv4{-*cmDZM#fP?c>ycFSpii z`6XTXai{o?Fl&x^OgOLU{oUE1>S?qa1D0j0XdcN#wg-oNIO6(#sZ z=E<9#b`DIcm8lX=y<3DAoLfC{#=eH8f1exA|76p*4qfxjXUYY=dD%I;9>}#7KDB># z{dC>A|E6~B*Pg|H_DO&L^C9Eqlxbo*>6H(Qru9cV75ZF{ShsA&`_tW0t+tC!w@h=> z&ul$8W9{RLKP%ZIrlua6HLv~dO_{Hu7ag|?Pe1S4e%v>^oMHOme#?_hk<0m>ZQ-0U zGx|p0Q-uY;R@&F}Z2tSYQ@1LbL-9z2)Kf*C-ni#t+bl!&_G}|1Z=N-Ii|omaqBRv2(Nb)|9?;s+xW8QNV*kudlrA{eSSib?uVnYoD$Bc>ihs z-LEzK7uG-8IoqT?;LK{>SHFu+cd2Ss9hsJS8=0l5YyfbY_nD^ln}XVCBbZVrqQwRX=B`-hx^VS71^uXB9P?M`zv{l z<9YW#e=hesoP7H4A79H!yZ%VA4C~L*^IpF?I-@{4e!fY+Yi8!2x9?n7ofP#I6(l~z z7JXj0x>|qt`LYGuz8h`-@!!C_-b^z6QGMantKwg4SI$_pNcl*t`>bW#&onIV^sBa< ztS*&tE8g?bl%!L_BD4Iz-7hY@c_Q!cLy^5-TmQx}Eo0GPQ{d@3*>+XJ_E`*v;*qI^ ztm_zNdz_!)FLzfa=hmTbn{WTzQOLdAv~|**OOAmzC#I&}KP>Kb?bB4r_|$Doit+68 z8atccH_rH}zUHh?XVl5nhOd4nZFF&U@7djF;F~`)>VRXf{%lp%IzJQh;!{R5U02%9 z>3X>Fl1IqgudH)R=WsnWRKMTV)VPK7>GQTNZpz?T{Lu5ad&v|RwdZ~eZ!OwwYt`*_ zOWKsfJLcZCaGF;9xwisbKqOAo>3MDNDjL+d%KfDE`n3{-9et_sK~={uF((eiW7k&j zCW0D*kAA7Xe<<6;>X5zPh5kp%?^(1|$ce-7SKHl2gJtKR?0)@h5_3b>^4-mkkMnK(mtbuB zYQt%BC!QyFzcAd7p5Sx%S$M^+Q{5%;ZcS~^&p5{2o8@tCN~O;E>4JueEjt2x?ud45 zn7qo(ex~crGto8ds-4n5uFuW=!FKM-s_wP=cBiiiMlam)$>dL;@taZ!&2#G#D))W$ z68GRxJR%{vldolQ*Y$h$j{cuQ_I*9#E8@R?LC$-zzF$65)>XCSPn-SQzT%}on`ScK z{rWvkXVyKgd83n1=&2QE^QQi_Zd?vmqMz*fyW7tuCk6_IHI-va+XJ#vgXl;Ah> zz}?f&H?Gj&?0&ZRbHE_dwAI#>z}VxUzXJV)3d*O+0|pCQSn#hn#?_? z9)6E|zO%|+YQYR4%@bZn*8I%OeSOTj#arRy^!4li3U#M_esXH&6xFtjRaU**Q@B#S znD^JFXgx82 zulC$;_UMgb=O3K@9vYDFX0_9`Gf!)ZJvm*E`F)eOIrWZB|0Qc?L}SA7z_@#x+I#<| zM?e3#ch9C&as79zmPfOmxq0XBfwel?n=S>F_T1&wYJJN6KDN*9&+5ylnm~nXguMSZjV;lJ1j(yR|gD zc`gQoI;VeAIn}nI&bdgkf1Sqi1CJg*`N+n!)L3KM?1WZf2Ve$uWl0XL4G7{wDW$CU3Q+@r&@>LqA@g+3dXFn{nLjYBBq*7Mr;u!b8sO z=}|T*S2f-p7<>%-_bj`4dE|*Lk_Qr0PqVemz4C3&{K(+soz1}qr_69+x^VTXw*&JbxmkA{ zR`v4CX42dHiE&o{s>8iMj*A*sd+DVIacy{zc7CHCQ?s4eE2{(j^`#1JM!hLNMSM8R z);NTx>(}vy%%5y#FCxiaduED5oS#%B^MAirhi=tRJ(#pTfgxtDT$96%#|zw@tpuDn z3Y(=r^0gT5Z0IWa<@aKpqFvjwLw(36n1@IR9;1y94iqm&`%I z67y4@xP<=~<#1*6mEN-F-~V8}n7R{}yQj-cx;%MdW?BEjYbg@Y7EY2G5se zI$q+dOsDE-8@$kJy;VGC{@+(WQoRK}umm(d@v%1G8*kq}cyX5Ap4`wkkjADR90)?0PU z$pL3Bg>cNXbX;nEj4xor+`Cuho`o-&#I{9d^}@f4vLu5~{e09cn$jly^R98Uh2V}i zlk^_Sr~PD-UA~e}%sBZ`(7ZiQMb6#P6gj>v%i-|#xbu>_^FKa4{ljYqWBtD+r(f`Y}dWtOq*C$Qf-Fa!ou_>IDDwVf>{F&_gr>I=I zj(186)4Q0BGurd#p6y{_ur3zUfAsLFcVuKj=dOse_s>Y@zf1T%(?B@w+_QU2izDqU zrI&8zb(e5h`u9Rw-R9+eYDEzS+na8m3NGCKjYrDq!i$wZ=bY``o3S%^$MsMnt|nI<+n({5+~{T!Q4<7eC&iL? zp-Qt{Kl+UFc3;Kw6)&H+2sp*atMnGPNK9J(;q7v-%e@Co^5O`P**m{K|(RLGzJxeDuL367r9ynD{BS?6B*-yL!#~V76?v%icvZ z3{v?Xa}+)KZ2Tq0buPPsapu*mu$AeSFF7VeSj_Zv`(QeMXUYs$4#k#^sU-?+Cuam5 zV&3krJXOKhz3fw3^Lwq`jR8j=f0-O**ed$8;o0(~&lvJ^v%5aJ`6;#tJPI;uQFNQi zlgOcXggT{90^o~}%CWIXxh)63}mk8!U}r!7eJdHii_`NXY%P2)0m9Xlo0oxQehn$o;K zk7}~w>)Yqvb*{O2=jxlR8+^xf-c{CEKJ(50^lfX|oUZJ18l?(8J=%Xw_v`5ID4Fy* z-RA4bvOk`ye?0C|->IuAd9}QUSN&h_|Gdn@6Tb1*ZO$;2WZ04U?#{{ESI=+Sc)Pc& zN%v6A#?7A}W-pa_xhd{KEKmU?HHu-a_@)=vx=K1fp2|J}8I@MfL8^s~x z`sYt;Q?b8(%PsDoXSrAE?ESC8ogBF}DgB-JwNDA>QkS(#SA6>}U#N9V+=q8rWme_C zol!Z$@19h1x7qENL+a04ue*5MEJXk6@9&odes|lh)4g8(cb#bRF4>+ZdOPOpFMs>+ zzS&lRqp+_77H{%XPfg+lRj{;TV3|C#Y( z&5>D_bF0(;=ie%?>Hp3y_R#iJUA&s;%<@lXXMf^&`={EB{gm>#@0(|wPFrw$V#8tc zANg84Q}ul2x|&Ev%c21 z@7coxv(FdaV3@%j@%^akmo@d>-)}iB$ZT1E==0_zPbJUSOOMuyis^;Tnt$xoCJwfbFhi`t=+W(dz`dIu14QuxB+ueVjr7$}lnD%e^oh)Ym)Ak>) zv-2lu|KdD8zy1E_$&Xc^yy}l#e!4kg^7P|!&t(OlS4+u%Y>B_6 z7V^>jd-?bKJVD35@4NE-d(+nTfcSYwtMd6L2QMg$=lk~at#FKe1OVfWO%ySIIQm}!2jY4*=^ZyD#+ ze>9$Ts39r!)!q09ecO2dWXbwj?rkBoW$`n#sB zAIt1b=jT28$vl^3i^p#l{%4nV|9B^)Z2QdTjjZ~L5H%zF+o#W!-%Af(opQV5^lql_ z4iX#G{Zv?2yv#Y!?X_X~Br~C#@A4=;U+U(4LW45(P zy_HsclJHtuf3t0=)%_Zc`Mv))&wSPRddaaZFH!@AW=8Ry-}_VR|6}tBlhO{07p4ZD zTB)J2PtC5TT7CIk$4Oq(KDckc@00x5jc@z>M^hfAX&HUHd_~S};}Zk(>!&CB$Fy)> zE=yqkU$Ub<=hvifehT-aj$dB?US)!1d;Z#)?ms{JhOljp+?mC;%=!Jt!^(S~= zANjyzirV2Br_O3WpA`3%(f-zZmE?0;|5jXaD8BOZ(vGL|Qhl=T9=!Zo`oj|cr=8W) zH*fhGYbPgRwkxN)?PX_({oYh7-;ZyFU*xnm_*J(RMQkmyI>!9|(_t_E*6y&+q1~q* zW~{y(JzxCNvOC9wjcao%Uc2&H98!5IK6$-HgHUDEp0|stWqRM%iRIirzW@Kf15eux zdKwO%JF+LQ?)#zQFVFO!MX&yKUEHHL;`@09(Ad=a@S^v-j@~feds5#x{Ns};CEK=b zJNosm*1G!e2bw&rt9R-%9~S3Y!1!>(Y=#8G$ek8;iZZVbvPbxo36(tSUauszY(noe zhY2kSM(lpk8*eS#Y&H3Dspgg+pz^&L?`%?GX0iV9r)T2I)Ri*=Hawjg{ATsyPm}I^JsnVc zWlqMywT>H>PZhiB*LSu-vzBSHkM0|bd#(<=1&PtY8W~3%+qz#m;!u|L?=(IlZYaKKZp>b3KhWy}Y%*pE;H>MAyf^SU1!*@owhf%;`J&7Yp7y zpOm?MmhuIvod+Uuh&ny`&Oc1!R^k|&leqjylks=!|8{|=cG(@|LWor{(!5c z&Hl#q_-#_U8Vwg`bg*)?{FxrpXFe-v17qU^_Vwp#3h!=9dHJlAOvqiLFQ|-0-c?{lCxMDJq#JmdQKWtWDUuWwURzYu~6(3t%o`PndMJ zCop{$A?(3m-id5a^#=)!v4HrgwV#e+ArU>cZ+?SpRc_4XU@qRXDjdge-ZWW zrGLNa4BjtWqzxTn-mctzrs6y2-M0)AZv}6>Wx&q1HGP42xkcNo7i-UFDBl%Yw*0x# z?|tXC?6{p8as1+mcjKryKjF7L^~iD7s}1b?4QHop zW@6;!5ew3N@R^nKwU708)s>*xcFPBc_on~Icr0lbR0RZ-yD`S z2%433)ZxRSzNT|q9&S0^A@5%JF1=aP>&^WBm~z(Yn-jvcSqfU?RGz-Rd8ADK#^?G2 z{m=d~+t0BRZIv?HIwy6(;(0Sar`8o**8g#HNfL+rqqoz6IIL6RLSQzMB=^nR@V& zq~#4!<&{T`XJo&BQV{J>eyd@^Zf^e|#>a1(_l1aX|5QCHqB_f9fgs=NjI0icb!(1? zp4;(qO0eN9!&ciZCBFj$J>=|XdU7_ul6dprv$5JUojL9+?TrQk{D=c=HC$v`@>}&I=cLasNm=|3l$u5Q7FT@VY^P=CFW?=;rfFE$?Y?d|Pf*8? zn3>|9t*a~Z{;&63Rnc{OlXk%0)OqP&v^Ph3>4-0?#ZnIBiSKt3Uv6^Y( z^X}=ETibJTWZs0GJkR|o*LO)c^ArKsrEwP~t$6v)`oNY1rmcP&XNxB!`z@|p@?M9_ z`sThu{Y>rf57&!zSIjf}mV5Wu!8qOvv#+UNi9FeMd3D8)mHHn&c1$&&_rHNzuJuTh zq|J^bOHH-b3A?ABx4UPyXVdFx#&Hu*OP0-f(ERG@o$n`_@4VxD@G@)pN$ZMO#dBe% z$uYrg<@vI)%=VUNcdn`YQMOE7Vq>JQ#_H=qVq6zDe2$H?SQ|VgzoYN=*`z~8Rm8z=kD&Y!&bmEOO!Mz7m1rC#mjti5caf85^k*q+^CpQlgWotgc1 z!PVt+=fD4ZHzF_k(ENI3$!@VDH=|Bp>woq2`ttDoS$k8DZTD|kl-JJD^fu>C%+Xs< zvw!qS9eDfZm|$1k`@Vm_Oy(T7f7aTfx~48cmOm=QMt19-{|_bqX70*eds(mR+?I{^ z&i{J-ewF2keVXQ<*Zwzc-|$~2fA23r_piS`e0-PgFLtaoe^Jie(1YvU z9{5hVAA8%)DCVMhVAsW^Dn3uLUoYGE{pfc~izytz!Fur#<=ppp^EWwey6h@a_&(h! zM$!Dj>NUJu-pxLwuN5jH(v3?<+ii9AlWEIab+?qe?HAErXUc^>pWFTMB%flE>hGC5w%v7rj!0`3{ayX%9cQt?P z^88-?-~MXp%O{HW?nNHGneo1=PhpwG`)sqU8y@!#vH!dl!`*(ba_aS2O%g(-)R$UDfxa zZT4Qbd^0<*Rp3#TQsKP=GmcjBXU+fByZ)0;Zb!=*p?AB>Is11;SN;lSU;Hil|ExZ# zFwRP55#LisZe8grjnQ1W?!f}#su{n0*MI)K>+^f%tA`R7y}ws=`=Co+q}-~@&YzAr zUHWGI^qCoS4Tr_K-!a^oTC1cE-Hkgu?^k7ws=4IkiziljOgwMPz-F{u=kfV>^8VWv zwx6<<|9tG?It|58tH8rATr-;EbP7~<1s=A0)T0vqVf)n!lOnzLEp6{9G7dG>OMA|r z^Vzcc7Hy%KwMe9%r_<4`oW3Ez2CiWybkd=^S=AD zU71$1)cRvPg7}qxK3HaG*dN&%c4zKIzeNp-jhrua_xyRY`Ojl((-hrZQ4e)ipIAwdb986{$bsU-wz(|A#m1IcvVp>o0xR&sz7r_4$vJzl>AP&voDF`+vCAff_?BHsT6SZX#kHDg!tYG9xN?NFR9Xa@V;W~`JnsH{PHwTq z`_9b^KWC^NfBmMyNo(@yI~t84b7nO*2tO0IJZZF4;B;-rM9G;OUIqSpzoF^ok_TB< zN3!Ra3#k};6*AAUs+e_c0o&TpH}7Vhd~}FqTj|$h)7?%z=y>EetEzfMzLd?!8XW`O zttM^xO2^X{T#~+jmqGkkLv}#@l=FMP8);uZ)Ho}nFvD@ys=0Ue7MV3JmVUt{&KqYW z{H|us{_ykrrK)aAzrOiu$D1a-Iqx^!KIrgl$Hyh#<}A4Q_|Qd(2irU=Z>-KPJPjHv zVo*8vo9k$0d*+>QeEL^@bN>4KgKbgo;#c-}%V28(Vtp<&?fCQ8^s3XBs?ar^(>_l; z?<}gj$ihjdU{6vPV}DG;^eN^`O_Se~;`{q`Rib&H zFH=?3_;I&!Md7_FB{z}&1Ip~;?!3pvnB``QWjt;!-_F2wa;LZ-ccpE~_qaRrE>5r9 z`F6pL&nr(DO`5m2ZU1cR57!k$Z>ss3^p!Nt5^#!{z3xP{!mmer-aokaNB)EIWz97+ zn;-4@oo{gB%ugeGk8=x@7C)$&Q?Br-#_>{n+=TAOd%UGC%G{J$>%GwXvd8?Z;?MVf zj}U8*;?Xc`wd|fFGQDzx?Dhw;H`6S|f9^3c7kqqEPUx5N{Al)Npw)KMC*CfZ^X|+^ zopUdiZn{|g?n$-Xx!)Fj5$m>Ui+xgmmY9>f?544i;L+M&i`&%GCL~#SyVo=RezflS zh7vbEb-ULG?#MI$yI7EP;I}55u-fIHas6Up=VQ+X@woY@J^uNxWz{R2w~G?aYcD)d zJ}Z6ReaBpZfH!CM{a1Xab^gGm8&+qI2ek@3`UMKx;5pmlo)|Zvu8ET?Nq&<0cn`DX z#Kmp?t0pRUE#_VRBK*mxz{B@0b}+IV82#(p`seO~{aflkvF*2#VCqS^yQS@a@#O`b zXQO{!{B`fNzL#Ne$UNT_AC+gZZ(ILt>9SSAuYHA2m~FeHqTeFm)FG|O?F?S=)-kb& zdGDzxIJ;Cq#GZ}>0O#Od0nuWqU5Dx4T7eTd_I{-S@X_S=@L1sGgzxb|+z z$K|mt>CcVx>dblfe_kM(8u;g}h!3NA`u}ZHAFOQ^Ia^ftO#JV~(`?MoIz5-%o9*Z| zk1CrzIEbYG!J&--U*^v}DSX_s+xnx{{yH7@z{LT6tWQ`hx*=ZypU=PiAA zQz5h7u&;;d!`@2{pYIu@EH{3)`{j(O0_*P2S-AI@%dhfokMqF?UN8Nto?bYS;t{mDv+{Jo~fZ|qn- zDJuU@{4~R(?fp9@_Hf9j_#~futb1DHYHZA3x0?S`YCU`AXj`{jyy2Xm-Xa{ii}yE+ z^1{ouC4W|lUVrdhIoE8Gn9Afm3NxRuYO09NS>F~k!R6H@6`d@G^T)z=ozsYzr0|9( z{=@6|w}Fhx&s12Q9Bq~#s+Daj zdD%;w(s&}R-^{L*_{pO59n^f?h{<&ETRw>%tO~1Lh zRzG;(jt1A8Q}^7Rcg%L;qr~xi+WnK~hPf3^np*HUukP=`%sZV&*X*fPt8e=DaOao2s_9?PGEO-XBv+pz7AwE+H2d3^clPJ8TI#-?VHD)Ksb%H; z?}qtu%O>Cs&N?VuUQr)(Qdw=szCHBTyKF&FRBK6`;d&N(7 z_p`fh=w0kv>~ULvMWbb{Q1-hS$ItL^x9l|ut2-nAZA;-&_u3;KW`y5x0AbGt>|I$O9r zH_qp?bw)w-%qgiyFRc6S$$Iqqk@o!ePqr9)1f3N6_u|{^%$$2C9wzeCYwWX{SHE{s z^>y82`(FCi&D`0gzI@5%t!u46{krw-wL&2ZSawQqU+eNTmAzWY&^?c)t* zPhFjsVD&}L-sY0`zozORvsn9Hgj(G>oVmQ!b*9)9zxO+}6PGQKDLVA_OrV^km*CI&ZXW>$?Xpzw%aGTK?(C-qVq{e(A~Y zHd4MGn{VeX`#w+m(d_N#pZ|E>?zuD9PV)Hn4_V#-y%$kAD2*=9aIl=X{Z~KY(v_nBVb=2eEY#FBcYE%-WX~XeqOI>!Rt!E8gCmy);;C z@8973`PVbW@78)QpW`R|)LT5@&W@S$_uT5bKj+Yn9NthXe)B!r7A*@C=1l84d)fQE zB!sAQk(^tbNL@7NvRb{EvXQZvX<(BHDQ^Va{n4zKGr+@0l|wo@>9o1l#& zQ|ZEe|MR~JzL0w1u;NGmkArCkmq=_#X^eWTc;o&}^B#ZYTBeM-i5pZWZMnet+Fw{`qOEE5}3b#+zbG1ME#HHpABO6Y21j<=9X+>1@@C1~ z`^OvCF{~0>wtVNbRr5aVtm1K*v>P<;cl+eVqXFz!-OqN4-H~Fcj>-)D{mgi&f5N1d zt+K~=bF5%ICu8eYyhTw}*TH-7^eu-{&Ri?B`FDkR%_*Zq-}8sx?3Bcira~Ze5njkNooOr$xW=-?!|uxUNkp*(BsE@M7VtF5z-Qc)Ae!SV!nAn6px8HtQ zbF4Wr?$(BNb}rrg|5JVM+s{3&_Q7#)qQ26We8D9S0>QmAtPMqr1cHSWeoBp`khS@F{pWw z!GtG`+4ilQk5%dQ+2wIdj{C)cAwm*2t^Qz*7 zZflvxY#m|e6t^umytnDa+s}n^?z?XLe-7STYdv3Y<%5at;uDvZ78ZOryJve*cW#ID zofV}DBGvJ0N_Ob>v@x#TuD|K#1e+D=Ya~1)lH7lumt&f)+vB$3lrzT$ACrYg3eIoX zs55m<=t_yYTQ1+X>DhRH+Mqt$;L*|BiE4X~xSe=&;415~n{F=(9=~S2d`QR0i#MY$ z&dR*v!;oLg;vCZE1jy*_w^tb}X7!obfjET;FCLtKT(i z-WGk_CsO+R>%51Hd((e-7)}h_Hf6p3?DI!v>4uz6mNDNFD1FG_iE5Im!-wXyS^q!l zoc;e&sfY3Q6K?&v(rQa4%qV&J=V5Z}mVfTbzS2wyUJ9ktUjC`cwJq6m$M3gy?SD(Z zxErsJCn=UL0pf9v563%ff)ZpA4DTl8AlmVb}j4n(jJx+c`?*Srw0G^8M|-JHzML&c4+%FIlEOnI$4rq`uK$Z~G~= z`R_i8pZ-^A>6k9N+^O=+$?c006mp#`SvS7ZDx4C$KK7Ab_c=TH_k~OL|J8XiT_ku) z#-Ro`i#3Z@DmoSMAK}ga(q?dJ(uuk|{=cjBYOcm@n6+{J8Kuo<7}VKo&n2l=&g-0) zD;~R`yyBw;?+ou?kJ!16MYEWg-!J?0yYRhzz1LQeB@?acKAhoNcJrl5eSz5ZGWK~p zJtcY_rtwa`+OY8m&(=gAO{stVOba45rhb!83FF@8^WoZVPL?+}+$>%xCDr^;=u}OQ z3}wo2+a*uY($8A5tN+;g{Tn9B zzJGtL=(f z{OKOYC;C|idg#nJ*sMKma#9e-&gh?S9_L;;{o^R_`(2%%<+6q3^%$nKbk^kFHTkyh zhaJ1E`L$yb6L-xnirAbd`H=tKlfBy>%E&H$6Q#LaAo;~E&da-gdDQ&)deWh&j&Y@J zdgdpGu$v;AV$w6d+~tsd?6z*Vz@wx~jS{Xx@^!XB8&Z8AZmbTUkQ4CH^3{z!PbKD> zAL(Ywf3k~PQO_(3GE%yu4z}yX2ehD0u?4Z1cL}p1xVt@>547S~v5krfg17M7{0+Y^ z)m_A)xUM1p|CjLaT^vpw*;5XEnQgL{KSFr&u~j-w9fr@!zsJ2);!s={Xw-u0m>eH# zfwa}VM_9PiQgyCt9og#G$FF!~Yswodfi}=u&LPAHJ$Z8PdRn5-#?^tyj|dtl<-&0o{XNC#y{Wf+WCZG!K0V&9{kwo zyvF{9PruchPrU-nmFBhwzKf|`-tbd&-nvhVs-LgeaqPr5QKycLW^ee8SSG56_SPA7 z7tP%MgU?II{KI1pw(o~dw0lmgQ;hqQ9|BG>$!_bIAFg<`^}GLt$u?8- zZ3~5uUe?yQy}Na>o$%7tat~)eU&mkm@tFL*@t-#$4?LO_ zvZmt3|7+2EZipP3V>NGg{_Nw27OAXZd6}`|(cXUkf-6_+JDoQg7Jg&8c4nT##JdhR zUOzeV@a~=+`(=- zE0ye$&tAFzxKuIq@cX^zioe#GI2fu1 zO_Y*q8c>-Mv5 zA78Hd>+|g5$~WHShWD?W+*hS6s+u{&_UxMaa_!qzP7&RU^Y72l;Ply9Y3lEL`jA=1 zPpQCD?K2-$nt#5~Q}b!^8Hs?xt=BhJzE*#e$G<31q4<;1yj@G@ICZzbYF@rEc1P*g z{(g*i-EX;*X;X6BM{84#M8L>( zlPg{=-2L-1`*Y(ujpVmj7cxJReJ$VmR=DMS>?6I=b-^F?H$x_?b#2k3zV_#kV=E2YYZyPsjc3f5Y9?7BDmi}a& z1J8w~FKoZXa?LdzX58Cc`X<{~ZD*36v2e+=x33g<) z*Qv`YOcUL(ZpEBRN%xF*UTJx*d~8)WKV56jdGX@+$(0g33mTtgK0VM`_9-ZBL)M_P$eB*|2@g1IXm`S9$2w^%ao=Ni|gK3knO)T#g9x|A`0QnP(^mY{3%wZskn4>n%i ztnuQ$bcnz0`Ze|*kB{01xF`O;@oDjy_iy4SR!!r#w>@aM`P8DD-I`v0ih+#&Q{GA! z|J@RH@8*v7=4B^)sdxlVp;x$>QXkm;;->)NJx~e|dJ^ z0Snfe<=Z~rpFNv1t>VYO$D2>sY=88B{@(9>{f~F>@7rJfmv66l6N86H*@kZ4B}bH2 zO`fD0xYt6j^Rb10*WVN8)${ME|FfukY;tttn;l0srfORL984@1 zIT|dc>~`K+xBK_MLI%!BJN6!CRMAM)+b!J{R&(yxWC^=^%&XU&fXcm5Uq#hlHh`MV@+lp!DXH%`KJ}+XNFX z<^DN)oxMIy>F^@vxifvZ6?U(9zjI1NXwuHVQw&s8l2~Q>?3lC^sxu0iHN`IJ3Vq3% z${$c0GC$*({l*EF!NnHy=k#-$v-??d@cfE8Q8=ak&&`Vxr%Yx&ooo=1JA=_ZT)s|J zWPW#+`gvy`6ok`zB1k zH=#?5b)vqUecPv(xo4tkw7>hDR!c3IyXg3m$p$xlUNp?}GiP)tvo2W4Bjs@9#DtH> zFYMbi*>?WC1qn}mmgz^F`oh}qohjPx&dG1v0wo@Du{0H)Ucs;M#q(##62W~5U-&+o z@`Ub8`nsp<{$o{^7ODLYu0GatYTkGIx*(IP!*qTR&t)2c=Ox|$zl@*c5XvsQ{(t=Y1WlOR5%~4uwP%NfFW<;o@-&$9XAMik5ff>(lZ{D!ikEqKcKr^kT2=8dJ=9Pn z{mX6jtY0%ESJk#l-WNE2MQ?u3+6+PIw6w+L<{u8;i;806)Y+HJxmj0XA!s#vLraQr zm4m5zg6!7i>>IbN_qzXc@t^Cb-3@PE(wu2D`}j1mO=T}#>~2T2=Wpp!65u!{yV$(J zWA-8Ea`B0Q6TGLfoI52v=j&>ZVsQ-TqC>JpQ$0 zUnO@$fXUpYcel=Y9lAkfX`q$karO5%b}Ez?FWJ;>>TSH^aig`z+D(tQr3B2naUkD* z#nNcjfREo==TCfocFhB`X5sDICkL1E?Rk4u=H1*gYbWPDeZBfz(Y>e>n?yL~**h<_ zKE@cZq4}?=oLI<`30zy|u3P-LYr~h5sWx8|SS5>$_y0SqK8KU1a>?os{Tpf;&lO)` z;ht%kDe14j{^(TWsfTWC>g$}i&EJ2^7sIJei)-C2Lf6a2Ti^9~xUl=UGJHbI+3B{s_Gg`FUsYSKVg6S!U1lBG1Gu z$aLopy?aYrJG5T=ea@Zc^h#Fl^s|YxST^nNe|Ai3j!}ct@sDr+1VtVBTig|4q0in_ z8zTQ&@(YLK(&g_sZl9jEaZ!TS_oobZk6Ye~jMw;Nr|QOvil$sR+IY(@DfW;2RKaQfU*|nvtGj%|+F6b_*Sst-yK-4VYhlKe zF7r#@I%nA}OWh~+*7{J}1-VN*5}V0yjeBR&t7Hr;g?hI74O-n zJUcyn%7#DNRA#Mum6>|#=>2Aqx8DP$m)2ao70!F{v0;EswjK8wD~E;G>!z8Pn?DwN ztpF-p1kBC_I!!m3`rc-9M-%t&pTB$4f2Z5!@swC`x^jwpY!dm{`#f*CO~B!9efb4} zdrp2|ny&IzJ7*44qe7fpz2H*|=k#+4$DZVLEkBp43^Qrq=G^DY4-cnwMC7a z&oOWcFAG@59{>91YProE`+7RQiE^+cH%mD52-JQ`k&7^$E7G)O&Yjc8)b8_c>)q6J z{HglVB(2q_8Ls+A-wnKX_o~oiC%=Qey&3V14hCi&?h;G~E!=Dl32?A{6e?v?x+i?* z$#bj6UgG+t`l)f(|FAGMIw(k-kFlS--9bTsgQaP9Tj3Tqr-cu;3D;zo{djt=uU2$V z#SNoH*L8b$^48=#TXQnVy8byWZMow}@$(LkZJstCF9>z%s_Cpd|6}|1b1|{;ze2)t zcXXe*oBy$Wn*L2~rC&bpDr;1a0kUNe%lRSR-3<9m|oql>)(4=sGp}XCFRha zsWv+e=Bxbr@#k*&Plb6_A{;E&d$Ua%3=B3tdH!dM&i_~aG5R0Qr0@QyzV4~N*1Tum zo~Vf2&$P4p{Ql3jwX(6V%zr+8RPD)rz&HDPoY~bseQWRLiKyrZUOL*>tD8Ty;8Nng zoDT__cBemoKe6X;k>JgE%aeO<&HPibzgK|kXm;Pn-j|96Vjmt~|D?YzkH6IC!SwY@ zH{{%n6gxU+e~WHD+v~6p1LeCcj^?^w)hmBrHvW73>g3G@vgen|J-EMptKj3hU~>uQ z;|r=@ReqgXrE|3W)7@6VNm_APeDcdQzxi4mYskLhwpi}>^yT`V&uXrn+4}LOd|cx8 z;5~Lq0yUC5+?Y9L-g_sTlXvb|(!9g3*5owp{rz*xZvOauLv{z3+58bNh#Rk2dHxclB8Ryr#Re<=a2m+svtgm-h-3-z+JyUTdL$`*678 z@-5=d;f%V!8P1^}G8emNdS%lm1uz zukEqM{`qIq^7(@&E&Lf^wvAQx%!!GXSJFFvhx*ngnf+|@vs;t3+??ghmf}w-6>LXm z>}|-u6YSS^w8e8*^LyVZfz7!&RmJL4?F>?<6#jqp^UOH|Wj+S^R}2ga44y8IA-mt! zY)luAer@}3riioJcl&)pr#p*hET0}UBf~B4-ud(PcJ0;+Cz!4l+nC|R)Yj0P{JZR9 zU8%X_S%oDhe#Tmc=AU^wQGME@ntI{gJjJF-7fuEEf4j4_rZkU@Gi_?{`@jD#ne4Nh zTrC&v8xYuQ>aw{~ER3Ynh#^xH{El9&?_*Y2ztZ z0by6}unl!?a*<)SireQl|1R77bdL1gFlpAqU#A%q+QskB)^atoFP)$N`0Br+xb7Rh znNQd3Pqy29$ycE|bKRdQ)A_e7PRabLYFacm^N5~u;_3Nk+e}5L+;G}*<;vpj%m=G4 zPUp#76SIAqYNps4wa(-7>zWqaIsTB}eDhM*kbOOD^z~L|^p%ywB;))30~ZPCT8emu&) zzJxOuC1Hd`0vHle=20@WokStMzxzeN*%N`y0QR2e-?eN`C!6XL*{% z`KY$r&#R3iHkYZjJ(mA)cyjF%-97E=XFo{UQdMa7;omx@eOt2_L-Xe={QSncB)s;} z>|Do?y>9WlyzXlY+_C977%d@`wwRM4UZa8QL{UU(j!{c*Yx6{B+aC;*54MFW$JR8i zkZ=;a#pJl=pi197^=D6$x{K78`|BiBO=_-Pe(U23qr1J!EgqdsD(lOwjU)*Fpvaii_dvokcl2>o;o0Vlk z0e?*9S)6T^Sl54jn?CRQ^Rq8?X_{}@xcro(182d%E16NwhF7??-W}7wabwEyHuiUq z^s-I!0s|Ei8Br>el$Of=GlC&h2_Op&KV63C+e?83syNBi75zt zdT`Z4{Q4&2U~~U}g}h7uioZWTzp(ZH#uby^N2Gl?WH&YQC)bQQITd$q&R;S6WT%$y zx(adK6+dL3-}v>>a+?=h5O>hnW*xtP~pZu!Fs>P-?INC6OT&ZZ|xIsnYf+uKY-h+EPU7tjLRd~5!R#T0f_vF=zHq7Cop^7)+&rLKe zd9$J}tL*)=&r3n8-jjkt*^hsF|LCvr-C4~XXRR)G#2Q5!u>Jb*<-f;N2l+h9Uoy2m zwdQecH=pySX)n95K%z;`=C9nu6}6sUFIVi6``;7!<*n7}RR0L2ud0i_I5s};J|n@S zAY${bs!Bsue=&piX6EcmCYu_>!hefizUx+G^n5a_iRJBrtR>yACpsBS>^BqL`0JgU z+MKy(-0yMQn8lx;c9zw|LU%$@qmcFvKhe!wBm4E1cK@EXW5zu3l=Y`gKIyK$DzNTZ z7N1qxCXKT#>r^W~rYL((k1w6lz`ozETV*i|qiBg*kk5n9tn70asDwQI6r}mj?#??a zvwi#8+Y)UaUp(V)q`2Bj?_PvAn@`*7^^?Mn6=>#(s@z?%M!MJBj-f%SGQ*Yqd`2=^w9M*4Pp~&0zOS;l6KQpUW=P?>yN2AT7-&Pp#JW_Kmm9(f2<8 zIs8Zd!(qwG6ILWg-)3dY+hVk7{^Os~b%(g0wkpV{2S-ci^_F~GQ}1A!@ZMxX!llb4 zW~|FS-Ab1guTq?;Hofl%llV&s%WA91k4+_ItY><5b5$;t(cD_;4g-#n9(GilzGLo?58E-hRX`@6C5 zL}g#{Kc;KvPAW(0E56iC@t<>M$`fsQvDm(}x=sCM+Z+GPVfo^r;-|6j#ipAt7AEhA zP}|PzpJXSz*miqoW5r`;2csaP?Nel$TTGYFam}<1+4jRB|A<0$#_Mm36()w5v=+U7 zuqo?!`P~UVPki;3C>(6y6O9ZDm@2Ta`}*aDr&oriPjY+X7|y(PVa&5dc?iB6Jy`}EU;g8d-|vS`)0Oy@;=&heRHvU z@|BW_pFanEy_xy!eyM)F>C)L{)#~3)-`mh3;{3yU;W{rntL@X;=T}a1PqBW#=a->7 z^UXE&6{5y#s&vwrFYT4q;BC#g_1kX!+}&&+8BfGX#Z=mSyBd9BO4W)x`zJH&%@j!g zu_I0OyZtAH)i#VaeSA@S43CJv|9WADaQqt&l_%$)9K5RSY39*#r)=MklIsiVBzNk& zuG%~ySovE5d-V43&52K|{yA|zC@X!;b96(W<7WL><}JTmRy4o8?f3bG?CT%5RqJN0 zdY#Gnq&;2O^wP}YXCFV9@ZY|-?%>K57X0s@b+^BJ^e{5_&$3A!wVnz)W_D^_?wT%r zzP0eD-;{5)qJMHk$`<{3&HGlR@kZyT({13^oWs8gWqFtC*non|N|EXxzp5`Q{_vIG zQf&RckT0qSEmCE2Q`a7@%h0l488Tr4$F8%=QZ@`NR-b;p58r&zdjXs8m#%}&4h7AN zl{NL}PnpNPr9xqIiPp@$&oi&xS?r=9z;o0>%E946?!k9*dmpdd)Y-Sruxf3fg20i+ z7S&>{{=3^}smyIUfAhdMf4|GBV%i)mho8-|1@!}&8XXEgD}A#RWq<9TfyP z_D%6Pv%~f3uO>^yk5yA$6?VM)akn-(mZi}_;YW~?Tq4+Q3KC{X42ocPCfta*&e(D> zNAY0RA&uDcF|60QFYaS%bTFvfQOC>?E401tX<*$4_wr2!fia1BR!O<>!HoC+Tu%Ra zeZAfygI7Xv6LM7l{MEZ8t-Io-Zyo<%*4kay`54#5#Do;;ZWq+X!&^y)ib5;*L@P> zN)HLB`XKE0lV{4B+LrvOlE3%AcrbUmeM0^FrIrlNzhd@%uV9tz)3Pglx;dqYE6qlx z?t5%pK4+qj=A(DFpKo5FAZYApHG9?12bUMmdG&VwqX{}bvo=roTHK|%;pK$Adgtcc zIRCocI^j{)zjyzdx*NsT-8`^=4dbr<&+FIAFZN|iE;1}%Kj-|TCKsPo{nKtu-n03& zNiS%!r9by(`KP~2GcEe|oVS-R5SVo4%&zZ(^K^qOJ|4Wi=h6#zRuyNapEEfnLhZkO z%iD8!22R{VGEy1RV1 ztwe0@=DxYPX>zWt;sJ@JwWTROk!OrgpPrHMDWLd`%(T;edan8L46#bZ;cJsCE2Vbb z6Wf-5`>?wBpA{0CbLzGE&z@1%zu3XodasXd+xtH~e`Ou7Xng$~sb0~!ZbDbeskFc0dC9Jg z^V%M}|M)ONw)mmXyxseoYHBT7&O~beymslN$cx<;HE%?I&)&1->GCADrn$?1{8eYa zajSl7X{hWI{`qenf358;(QYv8-YvhQSClpF)++za`#lq#ZaV#Ya!x2{{hGO}PpLn) zsBUu;y>wb_;$rrba}FQktomTSasAc$kAa%g;s?Im{`f3C4dgU|g|HolvaJyy*)uCvta;3Q7f)q#bwGc5i#|?@4`~NNB?0=^-@A&o2 zX^%?MRIY5!{}B5@;Hk6K`Fqb?MSSO++4CjYLfA{w)ZzWitaHZ;%H?|}PCFkHaLB}% zMf&@v`}0j6`j&ipeqLu;LV%oAv|;~U>)C()-CIy0_4DwvWRrG=k{6{7DM}|-9lu^S zFE)MEhxk3;w4~l@C!W+wTg0;O*4;m4)!GM3`0rQOm`VPql(guT+)2e9b3ak4>owTk>>bs)grnn-vz$TjzsH zh(}3Z*aap{bWwKTIA8Go!yUeuX8#`^GlX*`7}f3`yI)iLAzjT#$Lhk&lUo=zb^n^@ z-5IJnO>~Y>TZ_w@hQk-#9avNNb@LRCI_+|8id*}MaaI2-;j=%~#f;Lk_?}PxZ20im zflT&B$9QhbzEA!3)>6(h-8R<Ve;q^_AiZ8xvZ#r21oK1V@&6Q91{@7n^ z{P~Eb8OQuW!j+>d)Mj(aUby^Hjp0NdyWZ4)j4nKHtqmGJSQNH}1k~Kv?K~k*<>nIR zy;CE*^PkSkytyRC?D2x*OC~22aJFaJgVWAY#Pr01?~v(r}fzQA>reE=ONB4yV z@4uC{IB;Hg${aLF)9Xs{v5WT1ik=HrHTPZrumAGX<93_cij!)Zx`LCRC@k?-uxC8b zez^ST(~qk@we~;ET={6p`U$L;^B&qY%k9dxe6iz?m#Utm~)zullK>7Hy>(oc8&~C8uk8 zb5Ep8zkbmxp}TPXSDxd0SamdJoxAid>fBeY zh)I_;<}P?Vx%^Gcgx!`wH;>L*DtYJQ0of&CHw&YUG<Sq3M?Sx+#%dEa&Ghyd?XWLF2~3e^UJ1T0tJH zxBRYOEOd?d^~7ji)rKaXoipSAKNCL3(q?lh^oM)IK8NR)Sxv2H=4|O%KK=TmQ!~91 zb0XU>s%|cMt1Ds^y|TP2kVi;p!6_~-m)!fW`q<8`t`zZ&JaJdnv_k!?V*Q1Oi?`eL@H#i+}=G=-6!eN)72)dpjHd7#9qc0yQwRW zK6sn?{KU)0Id<3j;#udK&bJP~Z}ehOV)DC5N6)a%D%%opb?x3wL0`9jI(N*rVp{ly zf@?C%JQaTb&d6JHNRwHkMCSfE{iUvV?3Z`6elAkD;r?~wJjZ^4kg8XG8}{Z%YI7|s zis!pfJLfYm-=2eIX8E^xS3ldB@v4L?)P8L`|HpIhHt$H9=P)sI?V6>l7d7$hvIw|+ ze8t%*{TpgleYeTawQSA3%5y5sclqXp^Ns~@x^8^7zU{?F35|KC^I6km7hK4;KRtW* z?84)h_JuyLsC73xzfL3ZXRfD7=+(=orgY!$zqOCqcFT8}_=?Rtx7vuFtZiI-yYG@n zNT9U+{x;2hVS{1VytEC6q zlQxQe?|y0cL*->pLd3N z^|HxM6Q)hBzIo%x?t@~lG%I52g0z-x+Qk#_cgt1Tr*~s@4fURgfEsEKvW_V89Nggs zo{wny(P70b_@1-uQ}NuwrQOqaO*dMfT?d+v5a>x?H~(BT$Qq`DzK1QMm=^{V+~(Y8 zYW=4u{rEnvIGY^Fi?630yTi6``@*>_4Sh=gp7zSbB*iwexp}>-nNhkTR-;zg}dH#M*ALl+>Z2bRR{_R^A zm)1>=*V{L}gyGJXvbU+hXW!qr_14YtkdR{Rn;SPig>kCOK0D3EKkd8f5)RS)K%0n+@&O8U275J{oGfA?-zwpLQ z=dfdQYhF)#9+`U8QRn5NMT>7|9(^gj=i){uzfAqMbtO?>Y<(cp0sEZIerV`(G%_u* z)ZE5*OC}mJ74UBDmP^N^_y3ju_wjqRMdply#^1vy7|#&^6|1x0 zbJ~~vDTQHXd*81Ae0sAl3#0d~`GvDtZF2t~`Q9&kIOv0NopCW&`I9FbuL{~Zh5z>c zvtrf6JCnpKHs+YUE-towuuC~4)pj-!G7P`hD}w zH*XWYj7;QD9ox2`S<=#|{TGjNb!afFE9b+P`wleTWuN)$ij!D+=%$sv$EE}x`@8zN zvGw7eH`_iRofn(4_IpdZw+i>U0K6g^LSp7k&c?rCE1$%MLkkE z$(LtauiSI#yr3Xw_Pv;SdyVJc(vAN4#7QA3@mn$8;t{1o?f%SFzlZmNUg^O-m?#MTfKDTos@69#!Nv1b*WhE{JdzhRwk^42J zH&m}Fe%na}&}<&_u>`@Te9?zgCN*wbr?yAq%eRnAd@0M*l6Sp<47xKuS@v|&vWa^4 z=5{l`6|P7wx2k<%xjA2Gw-rOW-uoJhnaz5gEjH?w5tgyD{pN6K5v=YKx5JKZC0Pt#G&BrOjG0gj|Z9yS4?wB#Q`Z@5_l z7$f;s&+}z74xhL0X#l_7fs_r2S3Shz6|~wWv~F_{$TsL){QS&}+zX+T9YdXsa_d_E z1epgNX!5>#@fnkMWA~YhbG8RM|8Pp!B4MZ^W?*~r;J)Cu6(KX<9SfHEm}Y2woMlq) zrY|$(=`aH?{#)I zTXrnE|MPfD%7LVY1^OK+n-Zthe&IW_P@8cVb3mTqqRX>AjZc30!ef7pk-u%xsuNl( zy1JH3z7UNVsop*fGE)6lJW%rgfnR)~j$tJ)+-0`SYiaU%Ggs*7)14|;u3ui=<#;L4l=Wwg0-I?^`hs;= z1?DM42=TN`O$60V7m|3`1i0kNZEdGanjYA&^k$=Jrc|Uu_v*i0SN|XnGk-oFJS9O% zK36O0>)l=-3+tKvd&Dbp_RZ6s&7DyYrSOzVHLPH+R$BIExmYjp@4AJCw)!XHre}t1 zTQlvQxb5(qJz1hRaOCZ28UFj%`UA%y6SRw0|DNANt6x{QNNnP{As=n^Y z%##==EB=}q_woC~vg;c^ezi4;+1cPCfBRTW5Kn)Ap8K)VN5OHnvraJg>!sGtoO?aX z=2j|W!PUY$<>K6G&mPXz2>v;7vcf|~7nPEe!IdeIV$03*AC>3Yi8$-=+i$J8Anv0w z`?t2Q(Zr-_AF7){)4rf2ptgDIzInNCzBTH;ul$$zkN?NRo=lG`8`r))baXEx*0Euo z1ui6w4J)r?;8dB*80{tJ9j24AX!We~R!%2sbwj=`+nkeTX6EVd_0Z?p&0Q834ROFFd<^YtV)o$<4w`U!(?BS%kh_Tyirh ztwqY>UC+N4ZkMDDPsrWc^;g3~MbvlU9jlB3%95HhqrLhZ56ucbw`hx;R&)(yJj&3( zOxp9L>7Jq=&sD-~4!?~Q)%d4n7QXiYyPV|R1Fh$+CbNd|i_1jc4EZZ$y@yM{GIozd zaMg)Jhc@Q5?zy87SItzbrO>LO@v&)^M{M~Iu9a+Suk2o+a@}*A;nZV0+;kiCrXSz` zOQgkS%a!m?r+zQraGF7{EZ^4S)vT*E_47E7UOu;Q?rw`~;`3e?gw~$QzP9wv?*qa% z89^UPu6=$u?el`FmA~GYe15-c`ubU z`sU6>31$JGy6nYuE0F#b%~<2b{G}uecv0yi|wl zT(PNz*!`xLA1tksGm36jw)JO+75!J{-*ig&z~dJSQVV{j=<}|#k^B8hH^s{~bOkJJbJqK`Jo*(>R!M1an+e|SqJ|6+V<_kvVbJ@Q`vnfx{p>Ke}3`P zyXrRuJs+I%Po(`7)}CO0?*#kXqzj-H<6&Y3Ru7xH_@~{};rgBRBjAh>2aDsi3?bNB z0H%X8jQiLG1WKYe>~?=&u_|ZL;%t-hRso()#o6rhcC`PjvbMHcbx=`E6Vy(dVcZ8F zgw#DU&k|Hd2ynEWwWw-QEV;M1&u(g{^gE^E@6mr2rlu6-oiyuImy2@Rc(mo{SIPh1 zuFdQ&UHSFq)(2J3%lAr#)huJ0SC_^3HGlu{d+!A8th<)(KQe2+;^g1*@twP#&V9X^ zqio4fPdBwQu_q^UfA(C|fBt^$bpAIBU(DxZF*k5}e)oKU)%*W8_fM6}m&AO^VL5wc zp2nlM%qzcWe0;fw-M~NMT>15>5A43^>C2TIwV1H;9@krqpPJxhDkn`pxpJ;rJ}*3e z|U)G#>!bc%O#&>X>93S!1z5$Z?E>IbJ5P_ zYfoPbDtmom-tKAZ&z)5`xTfgU-uv-(s=7hLnczqOSt%sQ@`Yr4nHD*9iJ*_xFLj)*NtC7v>MpCB_*%-r{n!=JKRF+|QCD zV=Hq^jZC6tA>ZdOL0rOTPn`Yz^XKvBFD|aR%<(gGTfC9>^|h&5t@Pf(6EDx095rp=c)bU6B}K`FgFFWkK2M$|rIfx&TDa<#RgdzmcQ+;koe1e} ze!EuOqxk%CrTd2tX02Zqt-R)foz)j**4nHH=D6)s<@es~EW9MNZ)cWeZhp?vS#@{6 z-ky5r`w^j>+h(6G_iVMXHSL}I_U_+ZulLR=X7!x2XNrAXsrK2m(UuFR${W3Pw|_L> z?~DEAeQTC5-zt=s-}~FjeXdbwW$P2qMAgb8f0FJU{M1$Ta?MhsEwg^!bbB?cd3wnG zXzRr`k1lF0XJfuq_**XS&Yc$ZTq*y1+b5-d`~LIFQo;C!?y4{1_wRWtB#QY2Py5wi_;JlV9X7Q<{BctKsae*=Y;xf7#iu z`C^dxaqpjro)2B7C@IaxcA?psq@2PzcX2BAI;4D z^Qe6OrOAe~*Way|J{@&0dAV_0otmn_TAsL@Kh*v|zCLkI)X&H1)dj$iwK)9>ujZ`XeKXn$)wF5`S`!Bsw{gD;dy?#;4#|6%(k@$iq~=jS{+ zd9zOD>d~4T84`^i-tMQ4C!;dK>ZE96Hmhba^e5FT@^io>ulJ>WO&Z zSJ|gKgXUC~_`aq)oTx;!fAA3%p zI&Z&S@VZszNiWY#p}oFkzd|JQovlwzIq73!TA+5W_4=+3sRHI*2RKTue_XKLXkMPbHq#2p77UcZbyJvrSZRN*Hr~IQo%B`Cox4&p(+^;=c&sc(a-ZHGPlaZ^e zFlUdF~3m(}Sm3UgiEwkv=+ryH)lFl|zkGWr|e68R2Cb;XZPW**a zce7_{Ty1<~cGNt<@z6BunKkz<>ps7p{^R!i{YUQqd&Ixz?yBUXNULQlqTVeOy){d! zVC^NB%dy87zqxjy&;2~VQy%-gBQHQ zNWe$dSl%mbMKfooyE(aM6-xfxxaWz=%oDR?JRF-CWwkb~S)irp6u9nU)KAyYJ>G6! z&s$y}on+gp`m#2}tUB;pu_!ZQ25=}pVN{ymBhPTEOHOZaKF@0oXOv<*s*GN z-;{Wb*zSkz~}J z4Y#lM8jGC18la?Dug1SF&U2Ha(vxkUk1pSR=u~xbpIiOK6Z*6A;yzw_aOUB~=Xo#d zwUg9;#~LX<%4yGVIia8R`>6Al8_J6=@-ZFMFz$;p<{FPP zw6hm}-d8EOD!xC&an+r#s)o$%*%P;k(%`7Z9%@;mz8U(-Y|+;oez*aDlfxVNo@SK_Fh#iJi8%EHgqK8$`n zt@wIVkkG8`6_Nt&nYCrc1)GnX$9$Q2=kt@jKHIMc*k*lASn}kYd!^pysm{9h1Ye4{ zaWDM*&i%!n$0y#aU9F6_URVCR@U!-o`~^SqG*Y)Kwy(F@*YWMUT|)l%t?Or>_}J?> zUp&UV<(#yD)q4xc<5kb}dCjY(?>c1Ao=bIrX(; zKYQ=LmFM?Q-5(+P;Oh1L3tZV$j4!|Y$5pXX0oeJmft9hvS%sGGk{VcDEXZ`O! zzg_V)L!2?Rt6<+Zg~eZQK0Ute+1aNztv|24yJ@Pw9*f%-3%fXoyH=jF=9(yS>zxnp z-K}ml7jNm$+EuBM$JJW4=U3)hJCBsosx5V8n>BVnmFttS=qooVdvN8?-K?W_hwSWQ zp6vHtPXC(l<+{JQdv-1&TAhxFv2JoEi^Z$*E7 zn)c!C*1xp|6NEn2)LvQs@#axo4i%l9n=2okV|ukcS90?~=AM%bN_KP0ua#b^^q<8X zyWD6+)&{{-uNi)o-s?WBDRWhI@siJW&YPEurx!QeK3%-=>J{PlVxrSm&koJ7IV$+R z_RKlMz_ShKZo4l(-n-k{Vg0#&!|#*MRX1$-_9N_*aOs>6$1K$g0w?b^Tyv7GD(dx1 zMhCgSe}0wTJMVY?(4{+Fm)3u-Q=WCsTB=#())%wF8(SNW{tUBw&+&Ts{ncec0UWQF zr~C0P@7!$1e&uZReeTt>U#>}AzqiSnOZdjyHy35r#08m`U%YhPIobQm1vZge&PNwS zPV>?Wj!Isiwm(_STP@<|(-+-}-yDBs9{QE3QXFIGk~+a^uAFtQm*7n?*{K(QMK1ZV zg-xJPD0=tt$n;gy+iqptj^kgTo_+7`pO1&Wtk&abd=~rXczf^Sf4h6FziGIv5np>h z&0XF7-0PoSnOwK6=13Hu*7#z&;jC)1NB95jov)U^`(gRUk@eQA%xU?Gw--I`(fsuD zmrMAQ^L^J^i;dIIK3N(0v*dln^jzJ#D-yTfN3E?Cv&vuiS#G}7`wW+W4CyM9lIw-X z#3%2nJYjT?h3jqhviW`SbM5|3xoZ@=-0q>eY545Cs}tn;*)}cjd-vY#-3`S(4qs;O zo|(<|BJsHN>>DqqY<=zedAsDIt-DzNzMXvX*CQ6s;LU~Cw0A zajrakT zUnk5hulp?Yo@b&`(B3(lv%a5qaMyj#<2`d`vbyd0<0qTaFKXmDhR~Zq}Fbt)BgSQ%;&$`o0%O zZmiF{cTuh(ruUM|1-bbhljf`ao%P0A>|DCv>$*Nm5uqZk6UFAi;->o#cD>Y^6aM8_ z$NaCa_e|H1?h#t^cz<%G@4EPdG8@;ii`>!;{gToqdP_a3hUJ&k3f{FTdGlueTK2&8 z@0XW?SJETy)|h8MfAaCzM6)Wx$y4Y1N0lpIwT;SF@Ok2U$~8ZK=~d&H)^8UKGo~Fq zth%(+TlB8vMbTU8Te^kHd9L?xeAL_|^mMyr&ARg4?rzIIUooqbdB}GyeYR-)ZKlQd zo^QRdV)}~xXA{)j&q?3dkYUGG&usmBuGRHLbE2MS-&|d&_kMqj_NJ~!xk;bbCGFds zCAm3zdvVO-zj>P^IUogD+;iFWPSL$<=J(0PKlvtITKajq+d|ppby3>;iVahwI}2C6 z31f<@QaT&=!+nvv{9C*Au1~5u>(+4>F5D&h_gBy!c4EID?b?c*Xk^;E9PBiIAf!EKE-VatzAQ4-+!4S^oT$1enrJ?+-8{ucV-k%rEq zKlj?ogdB7h?GZY8qGhLcWl^G?=a-K^cfbGCSi5Amb>@Qi_b*j^kDgv_xoE1Z_T8^~ z&%Zva+J13@gyzoAiPv^+`|#*_-w(5NVGfq$rVEwdi|>})`(<*?X5YNqli2=moNHeH zTTtEYSJVyOBQIWeKMwECo|by0^ul%jM!TR#*~$yk#W+|JTh2-ESZ9@g^Jw4oxQFce zZ+E>zvfUbOM*h2MFZ;YzEsOhwLQh0Vz- zJiE!@mDi^qqA#Sl?(evIMe6vKHPcV*y|qGg{{0mzKliPX-M{BdxKl?B6F48dh#`|m*9)`N#%?fW!J#(h! z^@1DhFY~W%_!s6Uv8H|M%RHN-g85>bi+%q7-v4@L*sLZ-PVfE4wp~(d%E6CdEvBnYot#eeM1A ztn12tajY!bFJ>|E&ygReD|KI~zA|*5t?{+Ub8}9E1AnjX-s!wQ&PEznzS@`h<=wq& z>owGtl`u6Xyb-W^|9b7`J|~y2W-cK<*)Q|AUfF2%=VNxx;||~5Is)69D!1%B=k+N& zQ2*ks+AHZ7w!BhZRad3qTB!4qh3Q~~QpvsRk zdG#~?GuK&w%FF-Ok~hzP{G)6Cu=Ud+Z>#*?lET=>>#kJJP6apU*mnt5%zoAms7Eb=Ay^L4r+MEqZyEYwNUg^lO zI{9*>nX&ZjCF)D#`KuT0{m*k}{l>YwGwf9VeR#|*ap8s-+88bW^WN!+(_AOl=@w*J zoxHy5`Zw*9m!F?a_iGcJyF^`cd&ei0S{L099;YlfRqd=h&SP9sGwZ7oyw~CUdbz%4 zSF~otzMh+%K|UZ4-%u>McRlzy@59~}wztfNKO5B}ZtUlG$=$MLqR8c0nTuW~<_q-Z zUMcjf$@|)q8NJ+zVFvGBqO#s1J$0iV;<@7eE>gU>xdad9ld&7lFZg2tA z!EAd|_}{xI8H?P$=TS0dO6QWdy@;RW6k=1-VZVQI>(%aCCw5LayzuuOzH#M~1_JGrKNv&$-J(mTtBY9@t z`Tu0^l9=bg5=0LE7kh;e^<-j%5qV4 z%BQW%^OtU@<+s08q4)2)^LkP933X8hG3zE){kHnbc{TX_>h)KWHTO+^ueWDeBqvLg zg+#bj{@kOdS)?syP0B2tv2#mp%b6A<{#CYf%e>7~In!31pM9vAeerBl{_sx+&d9B~ zs~KV%6)5a{;%}yNoblaB^IdvOtdj~;G+OpBa-A|ZP@ZV9v1Q7=2VZAy?P!&)kp4<>?-`HMSpDKp3_c>d zJxg4sZFqVC@*QmhpxElyRM#$Di1<K3zB+?_R z80SuXw8gCM<8J?#Cuf|!{%(J7s_y%Zmsbk@KG4_Z{PI+1{7;#{x%VV51SDopQN34o z;Yxe9YPZbpWmVD6tK-&&>VGTaWvy!19R2^meP$0guDqSomlvNey0&=H&GpSvwTBi4 zrWan{>YyN@du-ylXvN|tc_y=2cbV1GM6c!^)?+vLJ=yYBg3>{@Z?8&L&7M>+qgvCG z<*Acc>BO*n$v+~?o8I^w5#2n`*u%TG+w=6Z2^VghSo%37MRk+m))_&`($%ZxvWVFC zs{0i$w7=_d<@U!HliWkZOdZ~CEWXjK6<2NgTej0@euAs`WVPQ}v6TwvBosDT-IbWk z_50N(4b8%B&C~2`xIP|{^ZmMZ<&^%embD3r{eG_#KY!D*N?oLVLHR3ZZ_K*Zyf_5` zp8k)EKVM^?F=JhWHmCdl*0|{xPF~*^cHV`-#^!TL_>bnN%YSrldHLtZ7J2DE|KH9n zFA06VbNT#OKYJ^ySFD~2ii#Iqgs+;JNf;dC)9dtpV{-q=vb#IAH_v%J_2e4U&1pvU zDmzc!Idf+3Ngt!QOumm6Wibk68#caN#wFm&#Hpfk<@ZEC{p$BWojpWe&rxPED*G{S zYs7(@>HB~GJ$3W<-S^>jKiJO}US726tp7eywp+R82A*dX?gabC?w|SaSYndp;`ysn z!h7^Pb!M)ep|o#frF7Mi_IT++uX$^}d{cQkN%i!T+JhaBc;mmF=y=HeDnceL#Z%RI zrq4HvqNnD{KV|%_YMp{^Joa4fzfD%?WV?FOq}2X+J5kF?EdAESp&ZnSJ^=iVoPA?aM2w_HdwqiYwhXL%l76IVIKf61Hc-ucJ% z<9Yt3#oZSbKYdMCee*x&x~o!h-0LQJEja#CIQeUWgu=<|EC%M6pR+O@T>G$Z;^(kf zJ0sN>`P+M94|halN>A9JttO?vLt@jh3%@U0UVgObuD;;s9hqE>R(mJr+f_BD%UPc- zH|H%%Jl#p3_68Q|7BlvEsDTi)^@sjNVD6K8crmKXVH>dh$<+pLBV7 zNYJw=yUbGia_yCEtcH_LrQE+|q~bJxiO9Dlw-p;}ETTH(_IuU!F|%?$-!jujUe?ny z>f6Vq+n2k%iViv%Un8GAIqnsu_)5kc|%{jm*S|M{hf^G%T3 zSoCefYpshqy=VRyv>3hM@l!cCd&Uh1CeJ4s`tSF~pP!s9_wfE}!9Vj9*^;MgXJ5K> zn=@sa@Tu7QE&5dxo*k5#_v_TA)5h=03lA(7RG#VcP34q9q?&fC?aMNQN2l78SuCqp z^r=eAKl=Gev1-@v7ks`UYSw*U$_(Ou9+-6EtV`{pi%zbQR^P6e?E8CFRr!AZ*H6>! zbC+AqWT~2CXXv$N|Fr#Pc@K)?e;N5_+}*P;)mr^eu!6b107qVjwadBa^k2KA_SvPY ze7~?QTXDZl?!J|UL7%s%#r?>+?_suR^$hv_vyN_vuu}u=R%ilP3Of=*x(`?Gt_Am)96o3|vsUCBofMr{@jg2`Z>KL z|C+cATOhkJ9vl;7Yyr1!nxx%W1Ry5nNeDV{sC9Jyao>M@yM1uM^Bg%P0S=b!LO0L$ zu*)r1I$g5ccIPqilVNA}w9iYp`uO~&Uk6z&)FdQT>cu1y+5GE0lD)+nH!x;uM{F!p zdlvYTJ$J^tVE2s7cWO&KSG=@aKC9{x~zq3DbAtzXJ2w>CHx zon4-F*F_C>a9Yh%y! z@Ms@tdttG)f9`vkC0FaakG4!LS+(yg)9cMym0#VXcNi%4cK8c;>3z5RFB`TrF5$NQ z|2E^p%3qV`elPuZx9#(vXZ7zE#WSlIOMbq->Dj)cQ=TkcAdy&O`_@GE{@Hu{=O6FY z={Lx$2A#d&To%0Hksepk-5IGDm~BhuSRFZPrtj92T=Yuk)T&dS6KlWBv+?lu*Lb-1 zSCq(_)^3gUI?7kogr!$3e|Vtqms7CjiFFTV{5J4ToBi_MXST0$yF5d)C$ncWmB<2F40DQbXVD_JYDhd1A~K>>*{dh^ZO^iJ>FKZ{*O`oy^KdkR_{-Fy)!OJ zQ&s2QACdDlhmXqFZJhhYJR(_ePu>Y1gJ&L7F_Z=8K^ zR*Zr`i)5C~sRy3=6IZlsEs*>?ecgfU-|cKCS{(nyzd&b>=Zhm{uMS_Hxjo6OFIN47 z?-#}?HUiT(GB8NI1)U2JdbCMZ@{8Q9Q#0$hFNfJXyquH9*7x1_W`5KrpJcbr9&?Sv zjT#4zi#vFH<5{!Ok?FDB#e6Z*>SfIypMQtUmvA|&vpnhQ-YGw~1zrDkalyOA`&Qi8 z^roeHugdi0GPcT+MO>G!*__*w!JfYDZPJ5R$rJT%MKx*sT)i@87V9p~$&nAUV!cjU zcJC~oE^NDT?yq;8E)36PJ{cV`~k-kJ$JGc@0MzyDbEIZG}+vTyS@3FSQR2rl8;*$__5BBL=Zb$=ebnZUzyBhcwa3kNx0ozvete02&%fo(UtHWwoOM{sKYw_B z-B|lP<#G@nzm+M#YbV*R0o4JG)Havq@pjYwb67)-uoA<(Jkz7t~oTpYraX zxTRr5uK3h9Pw#AB*YNFn{i)r@-E&)BX4@QlcPv>szU#7_QiT9V9%Ge2e))$_^(rd$ z0>0A?dQ^@#X#Y=mW4+1qSVz{!_%aoB%c-gozV9#HdFrn2Q9phDOUsojg5(9ARZ~A6 zK4Un4dGtKTyf$Xxy>o7FoPDoj@|)Ij!_5}VSMPg8_s@>`9M~uG%IDLE$s4DiQ7_#w zjr(Awh?TBKi+jzK;77NooY`?|TCmw}j&{wi{ZA!Ik4tgBTJUUb;>|@IcWce=M81qj zUVG)etxtRa`$@lJe?q5BeU{Mm?ZVAP34C+aS2RAENq3*`xMDl|)1Htg+XSMR;*Xsx&-(FNeU_uq-8%)_0 zvdvdgE%xUe`o3H0$=CQpc7J95HFvH(d9J4GbkW52zdt6P(9>4kzO(;a&rXpUw{Bc~ zu>0A=)Rx;8mj#mU?a7Sr`{7s`Y_)c7{Qp0`Y>N~k(?2{Ae}8z-_vwF5H~L+9#9Q;v zQvB0H7QY#vR>aJ4y1qL-^R3U(^7CA2ORp8=1UPRx_u!w)H=mz({@xLuGN*cG{NHaj zj@M(%YTkafx$@h-;;qhtT{CB1KD566pPHOz`_%jY#Q1eqq@KR0Sdwj+y}!i1kH7xt z{x`23bnhM!-}lJLuHxv{jO&T_e%(azpdAA|F}i>?CbU(tKuvAaA^CD z9cfmj`6jW&K4<3{2QB}4ZwI5}o^Lyz%+1)NBfue)td@K=ea75u*R+Off306~OMmQd zJ#<2Swnp@(POYQf?@wlJdBf%9&1JwpchSOi?GbZsuX&=Oa{cY{*DIcX%8zpj3zgW* z?2$GnlTT+F&m#8nf(nDKH$JYND|TpI4|=uhz{}kCf+e~MA8T7({EqD}kI{_Nb6pz7 z*0)9I#5#x4sELwpho>A^*0i`r_j4DU#s1I!U)=AA+%1-WYHVeBQ{>R3cTT3fk5=FH zOg`Xva96v=nY9c5CrL#A+#B+wB>4L|zqT`}A?wyVFL z4iA`9I?;IUWS_0GV|L^ywzaS4`7UkcVbsuL+o-SneEFkIEHCCJuqa1g&MOjHD(1$# zC9!kOsZ^iyn+0B4`6WjeywN`PA+vAaw${nH^1f01?Mr4%_$sk$l3&idahhj#Vt&y@eIr?yVK z_@L1=` z|N6VN!bIVke{ggEm6w?s4Vw9esX@BC`M37ou-iYoR($=d8@u|wkDtHrvUkC2#VY?d z%k(Dr7rHgg2>E{T$GtkHsr*4R>vF44EiSdXHTx;gw7SpspAYfZ9pJYAVb?$9)}w9h zGdOhw?r16TgzP_j@%y&m`are(L{>l3kA`Q1&+m+Vf4QKJf16?DR7@ z`$5QXX>z#gj%Axf*Q^xlS&*M{sY~#f^sYzSbG(nrWT_bZnkabCUZP9h)H{qT?9B07 zyQX&AG55rsyUJ5^{ZebnoBH_=RlcRTvz7hkk*oY?-?#Lu%1x%bVLn9+9Rd=wb(0rl zTW!*c|L3^VkX3s9lFK~?hyNbb-scteDa`K7-_=?t%2r4;9OZiM(<%SF>V9I`)wPcv zmM)E1vHR8Mj_DnmytgyvzG}X*=Zofe1o_RBJo8M zpw!l~aNdEA{;pyb?gza})?5Xee`6%}{CT80+u*cf%{>kewV*C>qs3bo+CyEZrGx}` zTsx4md8N=QZQ{-k#&wW_&1Mz5Gc-<9+(m&ztYO9LV&X!~X=UM`ld_3N#C*T5*oFFw8sDfKl~R4-yN8Qew=1u~#w{;p~aZq6X_av%fqL5X@#PYuy;i-e;m+bpFTnsX4}xMz_0? ze(Bu*x4yr(X2q-tOSH6#zi%+_w6!&GIADEXwtel~Yp;c6pFMKf+9@Zcl;n3*>9EI_ zg-OMc6MpOOo>;Blzs7snh)X*Mi>u3}Q#Xoj+SAX?gsP{+bi|gC|e0{4Zz_E-W`H7y@ySFuOW;kwnF0$2DicRg( zbba@=_Z_#Yw|DIpfAGroNWh++9V{;{Zv4G`R;1gmORmo6PrTB)IkVOBhO z=iq+#XUfLQs_B+fXUi>ADsOrnr+l~MTl5J{{R69J6o{Nx_RU^=dGd}3w~U5|E4tqt zD)HIWrMkO?XZC!>{cOv4t|;*z6yGlR_PyGkRPIEtfY{02b<&Mh-`>1g@Zh5U#nJL`u{XA9arQ6l_nR_hf=F|O54&!c+RT7Q|8h!|n&V2Ymt2xjyK+S+O>dsti#wid$_z%+ zzJy4;+n?vTuu<;IVrwps%_lvs)pUvZ9DnkDuaRVdjZdUV$dbqQpT)oJ-PXEyeQx6a zz9=Uzt~ASuzRfer1*|ZA`2T$u~C_A3-(09Axe&)%s zyh#q5CR^t7^?B$YT+yRy%xkl@;*TNERo{1uyyiTVYnnXIAyfHiuG*dV%#($$_bffL zy5vInBa?d(O7X{{-NE_s}PG3j@PeXZ_akAp9#Oz~AN z|9O|CFXZyY5Py5>NebVog{(OoS{+#}&`{MTh+yCfo zXe^c9f3keu#)fB0AAgaH`)ALd!7FXx7n9I3yQ2QIoSFSs-Ff$y7}k8$P(N3>^3MsL zG>5XlT}5mUXZ`nf?*G0jwcpO~ZC=XNXHTE}|9bVvw?(;c{(jY#=(js_|L=4k9hZ;a zO$vXluU}^9$=MrVET8jp!dd@6%J(DeeJZ~FQ3{UdoUffxHu zsQTw5^;asp++N53BI1(Y7q|aQ*FBCsJ?rbY#!lEwVN~`4<@6o05}VK3p-IxcQIbw3UHv=ihnn_+odfvS-=4 z-x{}ns5~{)XXdS5nJY0jU}eJD4T3M_{+(FW6_L*?zWaL6uLqaUNMtS57f^ZgU1dhT zVzOq8L*Esj+{YKDa<&QD2UbdnZJu*s*}eKnzqnV=DE&Wq$|Fh zS}^Ux)9rQMv$*$sbt$>fe*WT>ZEc&r&er@;&3UB6B;P*Kw(VX-cluSWRdOE$xhg)q zl)AX^-^cISGdR4s^p^J|A541}wLn<%)q>X-c5f-^?r80l^g2@jRBDl3QH*5*MUu?|(YvqQ@bOojkmOH=LCp-OGrT^&*bLx^ADj&8M z|GFD~vv5y){~C_Hy5Crs8XrvVX|XJqD?a_+S=Fm#$J}eo?)gR2AAt>soVHf9UkWm+ zX5J$8&A;wE8-!P`mLv?`NzcJzerB$qgT~C9Ux$QkCMhqgxf9q?CeFdqq^X?A@bO9b zyrj=x%@c|h*II+n##JSJ^u4)70l?#r?m(9rp-+c=~wk zzT5HhgKx)!h5-wbRcfV5*g}ooT(9%pwroPve7*nbp{#+5i)-vEZI@dbmh3Kfp1~Dw z_wG~eq*uY9%@^Be`$``^IlZu~x>RgQl;P58AJ3+XJ^uMxdykOMQL%45Zwl9?eVTcG z{lThLf~V&MbdaNbu@bYyG3Rx3oN=LwwGC+UTztn%zUM0M|YMzcPuSYz8|~PAm`M9d*yvmD`%`)qwstC zzQcX*G(Nff*>g;s^SADH%b;x^PYdkONfzASyU22?&CW!|rQbB(eifhSRb=`1R@k?A zS&g3H`OCIM+H9)h{CxTB0@lpcchA1(|JIYy?HSf3zV^w(R@ap1l0UWLKVN@ip7Z4u zXHBN++AP!lGiQ}gFBAA&Ui{_o-aWTp_}_|u6sJF7#a-dj1)A&pLFd|tY|eaqLQc|? zxnto!fo&$z*AC|7DDqmK?_7Gi_2~T*8~8MO-ZVt8>F@ohRnKvH$DJ@IFRkx65q@=- ztN*;XYUguQ`{%D))h~Y4zb{<0d{+FQZ!DJH=AT8sJJxMm{Q6Yb*{<2uW^2>@zT5r# z`qrD}QrhP?hqHIAu9n`-u0HAGgaWZpBlVI#@!jjAPH5lOJSY3;sQtbc{e0E`8xlEF z)5`;-JKv|kk;zK!4VZdu)X z9J1)&q&HO`Z`saJXqs{9mk0+-lfVArgUmh&9EWda|JdtjyBCXqI_f3?v|tL;>u+9 z9a)ej@NV~ke|g%)-IKT-dZ%c#wssr8TxIG1|Ehki+l*zCdrRC)|HO)CUVf7johp)^ zWWTtM|K5b@`x@rITgY+mpn=+Q$rTjIaUqXh5 zOy=8p|4rzavG8GL=7X9Wp8JeFSF7)in^We0WXiSWpndONJFO}jI8ziB-E(ZZ#*>!v z+C)BAJ@=STmyzxd>%ZYGW<3JTjBllO=HARXzNqy>-?MvPIh+M&q?#%U_pQFH5FNZ> zcG1m0S0?8eG4P~JK2xy1iO2J+?3u{oh`j8lz0V$Oy>FVt;`aGkn_tNEz$Gqqt4;`B z(D(Ly-PV}auu$4#Q;QL!{o|iSt8@KUtUI2q+|65j=J<+5tL1nFcKBIU-!YO%l=}AW z>4#Nb^D44f^O758F<0Lx%j;N?q1r4ARX@M1K_%JP-Exl4 zToRh=y8n&D$J)e}ihz z>%1vdDh?4RrEVr!CN<=!UFBIA@MV_tUX|Et^XrH0{`^zBS5YZ{)_m906)8(|KJqL| z-(IXa>CfxVzdZ}pD*}CAJx{5bx#Vo;)vp%0B78!Db8m<^FyBl$t`~26MPNVAto2jp zzTdhjILK3fZ}?SVG6-r#j!MZ109pG z<>^1d*8aR@`P%pSy2_h3R9mkss?^!`y?9mn7tbZaTrP&YFBir>bL!8(!tc;)zi4_r9@SZi{EvQfcV?qzaFXToH0=J=F;4GdFIqf zJN~L1ZCS`D=PsZmxXS-T&F;;natnD_4QbwJn1B z6%CyonVEG~f7y(8vvEjBJ>=uR=r!}5!z9k$S?zn@%O2hPuI}IAB;%?D?XP01S4c*S zB|gYqwQ$#?ynhc@cV9R(chApPe&<+h-&8+mc=kK&?9$(qo$f8<9{TCo z`GZ%B8g?DvUDEsb7w0sU=SRO6f7<7BD(%v)KIb*lzn5S6c;(mGKg*{k>RpXrVmqnc zQg{9e9-+QJl{RJnrD9gOoVkB?;@#?uP9}+pbMKz@Zws~g^1|3A?HcEo*e7$#qlI@H zRrI~(&HiylxPPOWfTF<#@871vvX8$`KN*|PbJJ(l<<^{8uOMZRcxMwkL+8%Z|J2^) zPg*-+`TRJq_t&;p?EnAmoxh>zz8aaQlXH&Nyq#$&Q~OiaPl|Q^j9-7Y6qVLqyW^n% zI-6tr%#?%7e|U3K*UkvNwTize4NfUHQMcIpq6sms_<#9Uw=} g&r_4KVfa&DslTaleYrvp0|Nttr>mdKI;Vst0CF~;DgXcg literal 0 HcmV?d00001 From 4cbb220764c99c5a3afb1269d374f7b451d52118 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 14 Jan 2019 19:56:39 -0600 Subject: [PATCH 140/970] Notes: Add task --- notes.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notes.org b/notes.org index 976be1a..66c2a54 100644 --- a/notes.org +++ b/notes.org @@ -18,6 +18,8 @@ This would be useful for having a menu of saved queries as Org links, or even bo *** TODO Bookmarks +** TODO [#A] Store query for refreshing ql-agenda buffer + ** UNDERWAY [#B] Dual matching with regexp and predicates :PROPERTIES: :ID: 39972bb5-fdd0-4754-93ba-c85796a67ccf From c5599a6030eb6f0b8e7a181cbbeb7c323a037d63 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 16 Jan 2019 07:08:05 -0600 Subject: [PATCH 141/970] Add/Change: date->planning, and new selector checks all dates/ranges Fixes #15. Closes #16. Thanks to @codygman for reporting, and to @swflint for reminding me. --- org-ql.el | 180 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 119 insertions(+), 61 deletions(-) diff --git a/org-ql.el b/org-ql.el index 93a1d6b..38d2dd7 100644 --- a/org-ql.el +++ b/org-ql.el @@ -176,9 +176,10 @@ a list of defined `org-ql' sorting methods: `date', `deadline', "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." (org-ql--flet ((category #'org-ql--category-p) - (date #'org-ql--date-plain-p) + (planning #'org-ql--planning-p) (deadline #'org-ql--deadline-p) (scheduled #'org-ql--scheduled-p) + (date #'org-ql--date-p) (closed #'org-ql--closed-p) (habit #'org-ql--habit-p) (priority #'org-ql--priority-p) @@ -285,66 +286,6 @@ Outline levels should be integers." ;; Check with comparator (_ (funcall level-or-comparator outline-level level))))) -(defun org-ql--date-p (type &optional comparator target-date) - "Return non-nil if current heading has a date property of TYPE. -TYPE should be a keyword symbol, like :scheduled or :deadline. - -With COMPARATOR and TARGET-DATE, return non-nil if entry's -scheduled date compares with TARGET-DATE according to COMPARATOR. -TARGET-DATE may be a string like \"2017-08-05\", or an integer -like one returned by `date-to-day'." - (when-let (;; FIXME: Add :date selector, since I put it - ;; in the examples but forgot to actually - ;; make it. - (timestamp (org-entry-get (point) (pcase type - (:deadline "DEADLINE") - (:scheduled "SCHEDULED") - (:closed "CLOSED")))) - (date-element (with-temp-buffer - ;; FIXME: Hack: since we're using - ;; (org-element-property :type date-element) - ;; below, we need this date parsed into an - ;; org-element element - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)))) - (pcase comparator - ;; Not comparing, just checking if it has one - ('nil t) - ;; Compare dates - ((pred functionp) - (let ((target-day-number (cl-typecase target-date - (null (+ (org-get-wdays timestamp) (org-today))) - ;; Append time to target-date - ;; because `date-to-day' requires it - (string (date-to-day (concat target-date " 00:00"))) - (integer target-date)))) - (pcase (org-element-property :type date-element) - ((or 'active 'inactive) - (funcall comparator - (org-time-string-to-absolute - (org-element-timestamp-interpreter date-element 'ignore)) - target-day-number)) - (_ (error "Unknown date-element type: %s" (org-element-property :type date-element)))))) - (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" - comparator target-date))))) - -(defsubst org-ql--date-plain-p (&optional comparator target-date) - (org-ql--date-p :date comparator target-date)) -(defsubst org-ql--deadline-p (&optional comparator target-date) - ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries - ;; that have any deadline. But the common case of wanting to select entries whose deadline is - ;; within the warning days (either the global setting or that entry's setting) requires the user - ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that - ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of - ;; course, that would make the deadline selector different from the scheduled, closed, and date - ;; selectors, which would also be unintuitive. - (org-ql--date-p :deadline comparator target-date)) -(defsubst org-ql--scheduled-p (&optional comparator target-date) - (org-ql--date-p :scheduled comparator target-date)) -(defsubst org-ql--closed-p (&optional comparator target-date) - (org-ql--date-p :closed comparator target-date)) - (defun org-ql--priority-p (&optional comparator-or-priority priority) "Return non-nil if current heading has a certain priority. COMPARATOR-OR-PRIORITY should be either a comparator function, @@ -410,6 +351,123 @@ comparator, PRIORITY should be a priority string." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) +;;;;; Date comparison + +(defun org-ql--date-type-p (type &optional comparator target-date) + "Return non-nil if current heading has a date property of TYPE. +TYPE should be a keyword symbol, like :scheduled or :deadline. + +With COMPARATOR and TARGET-DATE, return non-nil if entry's +scheduled date compares with TARGET-DATE according to COMPARATOR. +TARGET-DATE may be a string like \"2017-08-05\", or an integer +like one returned by `date-to-day'." + (when-let (;; FIXME: Add :date selector, since I put it + ;; in the examples but forgot to actually + ;; make it. + (timestamp (org-entry-get (point) (pcase type + (:deadline "DEADLINE") + (:scheduled "SCHEDULED") + (:closed "CLOSED")))) + (date-element (with-temp-buffer + ;; FIXME: Hack: since we're using + ;; (org-element-property :type date-element) + ;; below, we need this date parsed into an + ;; org-element element + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)))) + (pcase comparator + ;; Not comparing, just checking if it has one + ('nil t) + ;; Compare dates + ((pred functionp) + (let ((target-day-number (cl-typecase target-date + (null (+ (org-get-wdays timestamp) (org-today))) + ;; Append time to target-date + ;; because `date-to-day' requires it + (string (date-to-day (concat target-date " 00:00"))) + (integer target-date)))) + (pcase (org-element-property :type date-element) + ((or 'active 'inactive) + (funcall comparator + (org-time-string-to-absolute + (org-element-timestamp-interpreter date-element 'ignore)) + target-day-number)) + (_ (error "Unknown date-element type: %s" (org-element-property :type date-element)))))) + (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" + comparator target-date))))) + +(defsubst org-ql--planning-p (&optional comparator target-date) + ;; FIXME: I think :date selects either :deadline, :scheduled, or :closed, but I'm not sure. + (org-ql--date-type-p :date comparator target-date)) + +(defsubst org-ql--deadline-p (&optional comparator target-date) + ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries + ;; that have any deadline. But the common case of wanting to select entries whose deadline is + ;; within the warning days (either the global setting or that entry's setting) requires the user + ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that + ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of + ;; course, that would make the deadline selector different from the scheduled, closed, and date + ;; selectors, which would also be unintuitive. + (org-ql--date-type-p :deadline comparator target-date)) + +(defsubst org-ql--scheduled-p (&optional comparator target-date) + (org-ql--date-type-p :scheduled comparator target-date)) + +(defsubst org-ql--closed-p (&optional comparator target-date) + (org-ql--date-type-p :closed comparator target-date)) + +(cl-defun org-ql--date-p (&optional comparator target-date (type 'active)) + "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. +Checks all Org-formatted timestamp strings in entry. TYPE may be +`active', `inactive', or `all', to control whether active, +inactive, or all timestamps are checked. Ranges of each type are +also checked." + ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. + (let* ((entry-timestamps (save-excursion + ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will + ;; likely cause the action function to fail. We could wrap the call to the predicate in + ;; `save-excursion', but that would do it even when not necessary, which would be slower. + (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) + collect (match-string 0))))) + (pcase comparator + ('nil (pcase type + ('all entry-timestamps) + ('active (cl-loop for timestamp in entry-timestamps + thereis (string-prefix-p "<" timestamp))) + ('inactive (cl-loop for timestamp in entry-timestamps + thereis (string-prefix-p "[" timestamp))) + (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) + ((pred functionp) + ;; TODO: Avoid computing target-day-number every time this is called. + ;; Probably need to make a lambda that has it already defined. + (let ((target-day-number (cl-typecase target-date + (null nil) ; Calculated later. + ;; Append time to target-date because `date-to-day' requires it. + (string (date-to-day (concat target-date " 00:00"))) + (integer target-date)))) + (cl-loop for timestamp in entry-timestamps + for date-element = (with-temp-buffer + ;; MAYBE: Replace with ts.el eventually. + ;; TODO: Parse the element in the re-search-forward loop. + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)) + for this-target-day-number = (or target-day-number + ;; FIXME: Not sure if it makes sense to check warning + ;; days for non-planning timestamps, but we'll try it. + (+ (org-get-wdays timestamp) (org-today))) + thereis (when (or (eq 'all type) + (member (org-element-property :type date-element) + (pcase type + ('active '(active active-range)) + ('inactive '(inactive inactive-range))))) + (funcall comparator (org-time-string-to-absolute + (org-element-timestamp-interpreter date-element 'ignore)) + this-target-day-number))))) + (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" + comparator target-date))))) + ;;;;; Sorting ;; FIXME: These appear to work properly, but it would be good to have tests for them. From b11a3ea3cf6ac089266118be3ea908ebea9a043f Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 7 Jun 2019 21:53:20 -0500 Subject: [PATCH 142/970] Tidy: Docstring and tasks --- org-ql.el | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/org-ql.el b/org-ql.el index 38d2dd7..d356770 100644 --- a/org-ql.el +++ b/org-ql.el @@ -28,11 +28,12 @@ (defvar org-ql--today nil) (defvar org-ql-cache (make-hash-table :weakness 'key) - ;; IIUC, setting weakness to `key' means that, when a buffer is closed, its entries will be - ;; removed from this table at the next GC. - "Query cache, keyed by buffer. Each value is a list of the -buffer's modified tick and another hash table, keyed by arguments -passed to `org-ql--select-cached'.") + ;; IIUC, setting weakness to `key' means that, when a buffer is closed, + ;; its entries will be removed from this table at the next GC. + "Query cache, keyed by buffer. +Each value is a list of the buffer's modified tick and another +hash table, keyed by arguments passed to +`org-ql--select-cached'.") ;;;; Macros @@ -72,6 +73,8 @@ buffer. In this case, ACTION should return an Org element." :sort ',sort)) (defmacro org-ql--flet (fns &rest body) + ;; FIXME: Docstring. + ;; MAYBE: Use `noflet'. (declare (indent defun) (debug (listp body))) `(cl-letf ,(cl-loop for (fn target) in fns collect `((symbol-function ',fn) From 3b56bd14ddb2e705b660b28f432de86e1f431d48 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 7 Jun 2019 21:54:14 -0500 Subject: [PATCH 143/970] Notes: Add task --- notes.org | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/notes.org b/notes.org index 66c2a54..16fd957 100644 --- a/notes.org +++ b/notes.org @@ -2,6 +2,8 @@ * Tasks +** TODO Update commentary + ** TODO [#A] Tools for saving queries and accessing them *** TODO Save query from ql-agenda buffer @@ -9,6 +11,9 @@ *** TODO 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. From fc5647aea355ae632e1618f04959524f33a79b72 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 00:01:02 -0500 Subject: [PATCH 144/970] Change: Define predicates with macro, generate docs --- README.org | 92 +++++++++++++++++++++++++++++---- org-ql.el | 147 ++++++++++++++++++++++++++++++++--------------------- 2 files changed, 172 insertions(+), 67 deletions(-) diff --git a/README.org b/README.org index 8b799bd..1694f08 100644 --- a/README.org +++ b/README.org @@ -1,8 +1,10 @@ +#+TITLE: org-ql +~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). -* org-ql +* Examples -~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). Some examples: +More examples are available in [[examples.org]]. #+BEGIN_SRC elisp ;; Return a list of Org entry elements in the file "~/org/main.org" which have the SOMEDAY @@ -34,7 +36,11 @@ (not (property "key")))) #+END_SRC -** org-ql-search +* Usage + +** Commands + +*** org-ql-search The command =org-ql-search= prompts for a query, a list of buffers or files, and how to group and sort results. Without prefix, it searches the current buffer instead of prompting. Then it presents the results in an agenda-like view. @@ -44,7 +50,7 @@ Here's an example of using it to generate an agenda-like view for certain files [[images/org-ql-search-snippet.png]] -** org-ql-agenda +*** org-ql-agenda Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries and present them in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: @@ -101,6 +107,28 @@ Here are some other examples: (closed = today)))) #+END_SRC +** Predicates + +Arguments are listed next to predicate names, when applicable. + ++ ~category (categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). ++ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~date (&optional comparator target-date)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. ++ ~habit~ :: Return non-nil if entry is a habit. ++ ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). ++ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). ++ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~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. ++ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). ++ ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). ++ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~tags (tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). ++ ~todo (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). + +* Notes + ** 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 [[https://orgmode.org/worg/org-tutorials/advanced-searching.html#combining-metadata-and-full-text-queries][advanced searching tutorial]], it would require using ~org-search-view~ with a query with specific regular expression syntax, like this: @@ -117,14 +145,60 @@ But with ~org-ql-agenda~, you would write: (todo "TO-READ"))) #+END_SRC -** More examples - -More examples are available in [[examples.org]]. - ** org-sidebar This package is used by [[https://github.com/alphapapa/org-sidebar][org-sidebar]], which presents a customizable agenda-like view in a sidebar window. -** License +* License GPLv3 + +* Code :noexport: + +Code used to update this document. + +** Predicates + +Generates the predicate subtree. + +#+BEGIN_SRC elisp + (defun org-ql--readme-predicate-list () + "Return an Org list string documenting predicates." + (concat "Arguments are listed next to predicate names, when applicable.\n\n" + (s-join "\n" (->> org-ql-predicates + (--sort (string< (symbol-name (plist-get it :name)) + (symbol-name (plist-get other :name)))) + (--map (-let* (((&plist :name name :docstring docstring :fn fn) it) + (args (->> (help-function-arglist fn) + (--remove (or (eq it '&rest) + ;; Comparing the symbol itself doesn't work for some reason. + (string= (symbol-name it) "--cl-rest--")))))) + (if docstring + (progn + (setq docstring (s-replace "\n" " " docstring)) + (format "+ ~%s%s~ :: %s" name + (if args + (format " %s" args) + "") + (unpackaged/docstring-to-org docstring))) + (warn "No docstring for: %s" name) + nil))) + -non-nil)))) + + (defun org-ql--readme-replace-node (outline-path string) + "Replace contents of node at OUTLINE-PATH with STRING." + (org-with-wide-buffer + (-let* ((subtree-marker (org-find-olp outline-path t)) + ((_headline element) (progn + (goto-char subtree-marker) + (org-element-headline-parser (point-max)))) + ((&plist :contents-begin beg :contents-end end) element)) + (goto-char beg) + (delete-region (point) (1- end)) + (insert string "\n")))) + + (defun org-ql--readme-update-predicates () + "Update predicate subtree in current document." + (interactive) + (org-ql--readme-replace-node '("Usage" "Predicates") (org-ql--readme-predicate-list))) +#+END_SRC diff --git a/org-ql.el b/org-ql.el index d356770..bf1be9b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -35,8 +35,23 @@ Each value is a list of the buffer's modified tick and another hash table, keyed by arguments passed to `org-ql--select-cached'.") +(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.") + ;;;; Macros +(cl-defmacro org-ql--defpredicate (name args docstring &rest body) + "FIXME: docstring" + (declare (debug (symbolp listp stringp body)) + (indent defun)) + (let ((fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) + (pred-name (intern (symbol-name name)))) + `(progn + (push (list :name ',pred-name :fn ',fn-name :docstring ,docstring) org-ql-predicates) + (cl-defun ,fn-name ,args ,docstring ,@body)))) + (cl-defmacro org-ql (buffers-or-files pred-body &key sort narrow markers (action '(org-element-headline-parser (line-end-position)))) "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. @@ -178,32 +193,31 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (cl-defun org-ql--select (&key predicate action narrow) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." - (org-ql--flet ((category #'org-ql--category-p) - (planning #'org-ql--planning-p) - (deadline #'org-ql--deadline-p) - (scheduled #'org-ql--scheduled-p) - (date #'org-ql--date-p) - (closed #'org-ql--closed-p) - (habit #'org-ql--habit-p) - (priority #'org-ql--priority-p) - (todo #'org-ql--todo-p) - (done #'org-ql--done-p) - (tags #'org-ql--tags-p) - (property #'org-ql--property-p) - (regexp #'org-ql--regexp-p) - (heading #'org-ql--heading-p) - (level #'org-ql--level-p) - (org-back-to-heading #'outline-back-to-heading)) - (save-excursion - (save-restriction - (unless narrow - (widen)) - (goto-char (point-min)) - (when (org-before-first-heading-p) - (outline-next-heading)) - (cl-loop when (funcall predicate) - collect (funcall action) - while (outline-next-heading)))))) + ;; Since the mappings are done at runtime, macros like `flet' can't be used, so we do it manually. + (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. + (save-excursion + (save-restriction + (unless narrow + (widen)) + (goto-char (point-min)) + (when (org-before-first-heading-p) + (outline-next-heading)) + (cl-loop when (funcall predicate) + collect (funcall action) + while (outline-next-heading))))) + (--each orig-fns + ;; Restore original function mappings. + (fset (plist-get it :name) (plist-get it :fn)))))) ;;;;; Helpers @@ -242,16 +256,16 @@ Or, when possible, fix the problem." ;;;;; Predicates -(defun org-ql--category-p (&rest categories) - "Return non-nil if current heading is in one or more of CATEGORIES." +(org-ql--defpredicate 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))))) -(defun org-ql--todo-p (&rest keywords) +(org-ql--defpredicate 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." +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 t) @@ -259,11 +273,13 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (symbol (member state (symbol-value keywords))) (otherwise (user-error "Invalid todo keywords: %s" keywords))))) -(defsubst org-ql--done-p () +(org-ql--defpredicate 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--todo-p org-done-keywords))) -(defun org-ql--tags-p (&rest tags) - "Return non-nil if current heading has one or more of TAGS." +(org-ql--defpredicate tags (&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-at' for every heading, especially with inheritance. (when-let ((tags-at (org-get-tags-at (point) (not org-use-tag-inheritance)))) @@ -271,15 +287,13 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS." (null t) (otherwise (seq-intersection tags tags-at))))) -(defun org-ql--level-p (level-or-comparator &optional level) +(org-ql--defpredicate level (level-or-comparator &optional level) "Return non-nil if current heading's outline level matches LEVEL with COMPARATOR. -If LEVEL is nil, LEVEL-OR-COMPARATOR should be a level, which -will be tested for equality to the heading's outline level. If -LEVEL is non-nil, LEVEL-OR-COMPARATOR should be a comparator -function. - -Outline levels should be integers." +If LEVEL is nil, LEVEL-OR-COMPARATOR should be an integer level, +which will be tested for equality to the heading's outline level. +If LEVEL is non-nil, LEVEL-OR-COMPARATOR should be a comparator +function (like `<=')." ;; 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))) @@ -289,11 +303,11 @@ Outline levels should be integers." ;; Check with comparator (_ (funcall level-or-comparator outline-level level))))) -(defun org-ql--priority-p (&optional comparator-or-priority priority) +(org-ql--defpredicate 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 +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." (let* (comparator) (cond ((null priority) @@ -326,11 +340,12 @@ comparator, PRIORITY should be a priority string." (org-get-priority (match-string 0))))))) (funcall comparator priority item-priority)))) -(defun org-ql--habit-p () +(org-ql--defpredicate habit () + "Return non-nil if entry is a habit." (org-is-habit-p)) -(defun org-ql--regexp-p (regexp) - "Return non-nil if current entry matches REGEXP." +(org-ql--defpredicate regexp (regexp) + "Return non-nil if current entry matches REGEXP (a regexp string)." (let ((end (or (save-excursion (outline-next-heading)) (point-max)))) @@ -338,12 +353,12 @@ comparator, PRIORITY should be a priority string." (goto-char (line-beginning-position)) (re-search-forward regexp end t)))) -(defun org-ql--heading-p (regexp) - "Return non-nil if current entry's heading matches REGEXP." +(org-ql--defpredicate heading (regexp) + "Return non-nil if current entry's heading matches REGEXP (a regexp string)." (string-match regexp (org-get-heading 'no-tags 'no-todo))) -(defun org-ql--property-p (property &optional value) - "Return non-nil if current entry has PROPERTY, and optionally VALUE." +(org-ql--defpredicate property (property &optional value) + "Return non-nil if current entry has PROPERTY (a string), and optionally VALUE (a string)." (pcase property ('nil (user-error "Property matcher requires a PROPERTY argument.")) (_ (pcase value @@ -386,8 +401,7 @@ like one returned by `date-to-day'." ((pred functionp) (let ((target-day-number (cl-typecase target-date (null (+ (org-get-wdays timestamp) (org-today))) - ;; Append time to target-date - ;; because `date-to-day' requires it + ;; Append time to target-date because `date-to-day' requires it. (string (date-to-day (concat target-date " 00:00"))) (integer target-date)))) (pcase (org-element-property :type date-element) @@ -400,11 +414,19 @@ like one returned by `date-to-day'." (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" comparator target-date))))) -(defsubst org-ql--planning-p (&optional comparator target-date) +(org-ql--defpredicate planning (&optional comparator target-date) + "Return non-nil if entry's planning date (deadline or scheduled) compares with TARGET-DATE using COMPARATOR. +TARGET-DATE should be a string parseable by `date-to-day'. +COMPARATOR should be a function (like `<=')." + ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. ;; FIXME: I think :date selects either :deadline, :scheduled, or :closed, but I'm not sure. (org-ql--date-type-p :date comparator target-date)) -(defsubst org-ql--deadline-p (&optional comparator target-date) +(org-ql--defpredicate deadline (&optional comparator target-date) + "Return non-nil if entry's deadline compares with TARGET-DATE using COMPARATOR. +TARGET-DATE should be a string parseable by `date-to-day'. +COMPARATOR should be a function (like `<=')." + ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries ;; that have any deadline. But the common case of wanting to select entries whose deadline is ;; within the warning days (either the global setting or that entry's setting) requires the user @@ -414,18 +436,27 @@ like one returned by `date-to-day'." ;; selectors, which would also be unintuitive. (org-ql--date-type-p :deadline comparator target-date)) -(defsubst org-ql--scheduled-p (&optional comparator target-date) +(org-ql--defpredicate scheduled (&optional comparator target-date) + "Return non-nil if entry's scheduled date compares with TARGET-DATE using COMPARATOR. +TARGET-DATE should be a string parseable by `date-to-day'. +COMPARATOR should be a function (like `<=')." + ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :scheduled comparator target-date)) -(defsubst org-ql--closed-p (&optional comparator target-date) +(org-ql--defpredicate closed (&optional comparator target-date) + "Return non-nil if entry's closed date compares with TARGET-DATE using COMPARATOR. +TARGET-DATE should be a string parseable by `date-to-day'. +COMPARATOR should be a function (like `<=')." + ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :closed comparator target-date)) -(cl-defun org-ql--date-p (&optional comparator target-date (type 'active)) +(org-ql--defpredicate date (&optional comparator target-date (type 'active)) "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. Checks all Org-formatted timestamp strings in entry. TYPE may be `active', `inactive', or `all', to control whether active, inactive, or all timestamps are checked. Ranges of each type are -also checked." +also checked. TARGET-DATE should be a string parseable by +`date-to-day'. COMPARATOR should be a function (like `<=')." ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. (let* ((entry-timestamps (save-excursion ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will From 4d186d705449d94fa21de0c6433a28a65f0268ba Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 04:24:50 -0500 Subject: [PATCH 145/970] Docs: org-ql, org-ql-query Also rename org-ql--query to org-ql-query. --- README.org | 30 ++++++++++++++++++++++++++++++ org-ql.el | 6 +++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index 1694f08..b1903da 100644 --- a/README.org +++ b/README.org @@ -107,6 +107,36 @@ Here are some other examples: (closed = today)))) #+END_SRC +** Functions / Macros + +*** Macro: ~org-ql~ + +/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ + +Find entries in ~BUFFERS-OR-FILES~ that match ~PRED-BODY~, and return the results of running ~ACTION-FN~ on each matching entry. + +~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql--query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. + +~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. + +If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). + +If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. + +*** Function: ~org-ql-query~ + +/Arguments:/ ~(buffers-or-files query &key action narrow sort)~ + +Return items matching ~QUERY~ in ~BUFFERS-OR-FILES~. + +~QUERY~ is an ~org-ql~ query sexp. + +~ACTION~ is a function which is called on each matching entry, with point at the beginning of its heading. For example, ~org-element-headline-parser~ may be used to parse an entry into an Org element (note that it must be called with a limit argument, so a lambda must be used to do so). Also see ~org-ql--add-markers~, which may be used to add markers compatible with Org Agenda code. + +If ~NARROW~ is non-nil, buffers are not widened. + +~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~, and ~priority~. + ** Predicates Arguments are listed next to predicate names, when applicable. diff --git a/org-ql.el b/org-ql.el index bf1be9b..06c8438 100644 --- a/org-ql.el +++ b/org-ql.el @@ -58,7 +58,7 @@ This list should not contain any duplicates.") ACTION is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to -`org-ql--query' as a lambda. By default, `org-element-headline-parser' +`org-ql-query' as a lambda. By default, `org-element-headline-parser' is called to return an Org element. SORT is a user defined sorting function, or an unquoted list of @@ -81,7 +81,7 @@ buffer. In this case, ACTION should return an Org element." ;; maybe this should be on the agenda-ng side. (->> ,action org-ql--add-markers))))) - `(org-ql--query ,buffers-or-files + `(org-ql-query ,buffers-or-files ',pred-body :action ,action :narrow ,narrow @@ -98,7 +98,7 @@ buffer. In this case, ACTION should return an Org element." ;;;; Functions -(cl-defun org-ql--query (buffers-or-files query &key action narrow sort) +(cl-defun org-ql-query (buffers-or-files query &key action narrow sort) "Return items matching QUERY in BUFFERS-OR-FILES. QUERY is an `org-ql' query sexp. From 2722d874605b13ae48cadd75df1820438b2b46b3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 04:30:52 -0500 Subject: [PATCH 146/970] Tidy: Docstrings, symbol names --- README.org | 12 +++++++++--- org-ql.el | 16 ++++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.org b/README.org index b1903da..ead7d66 100644 --- a/README.org +++ b/README.org @@ -113,9 +113,13 @@ Here are some other examples: /Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ -Find entries in ~BUFFERS-OR-FILES~ that match ~PRED-BODY~, and return the results of running ~ACTION-FN~ on each matching entry. +Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. -~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql--query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. +~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). + +~QUERY~ is an ~org-ql~ query sexp, unquoted. + +~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. ~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. @@ -129,7 +133,9 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to Return items matching ~QUERY~ in ~BUFFERS-OR-FILES~. -~QUERY~ is an ~org-ql~ query sexp. +~BUFFERS-OR-FILES~ is a one (or a list of) file(s) or buffer(s). + +~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. For example, ~org-element-headline-parser~ may be used to parse an entry into an Org element (note that it must be called with a limit argument, so a lambda must be used to do so). Also see ~org-ql--add-markers~, which may be used to add markers compatible with Org Agenda code. diff --git a/org-ql.el b/org-ql.el index 06c8438..20667ec 100644 --- a/org-ql.el +++ b/org-ql.el @@ -52,9 +52,14 @@ This list should not contain any duplicates.") (push (list :name ',pred-name :fn ',fn-name :docstring ,docstring) org-ql-predicates) (cl-defun ,fn-name ,args ,docstring ,@body)))) -(cl-defmacro org-ql (buffers-or-files pred-body &key sort narrow markers +(cl-defmacro org-ql (buffers-or-files query &key sort narrow markers (action '(org-element-headline-parser (line-end-position)))) - "Find entries in BUFFERS-OR-FILES that match PRED-BODY, and return the results of running ACTION-FN on each matching entry. + "Find entries in BUFFERS-OR-FILES that match QUERY, and return the results of running ACTION-FN on each matching entry. + +BUFFERS-OR-FILES is a form which should evaluate to one (or a +list of) file(s) or buffer(s). + +QUERY is an `org-ql' query sexp, unquoted. ACTION is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to @@ -82,7 +87,7 @@ buffer. In this case, ACTION should return an Org element." (->> ,action org-ql--add-markers))))) `(org-ql-query ,buffers-or-files - ',pred-body + ',query :action ,action :narrow ,narrow :sort ',sort)) @@ -101,7 +106,10 @@ buffer. In this case, ACTION should return an Org element." (cl-defun org-ql-query (buffers-or-files query &key action narrow sort) "Return items matching QUERY in BUFFERS-OR-FILES. -QUERY is an `org-ql' query sexp. +BUFFERS-OR-FILES is a one (or a list of) file(s) or buffer(s). + +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. For example, From 13d3c1c4d92bc4e564d94b82f16e4a98036ca7e1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 04:45:14 -0500 Subject: [PATCH 147/970] Docs: Queries, etc. --- README.org | 59 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/README.org b/README.org index ead7d66..670864d 100644 --- a/README.org +++ b/README.org @@ -107,6 +107,32 @@ Here are some other examples: (closed = today)))) #+END_SRC +** Queries + +A 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. + +*** Predicates + +Arguments are listed next to predicate names, when applicable. + +Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation. + ++ ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). ++ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~date (&optional comparator target-date &optional)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. ++ ~habit~ :: Return non-nil if entry is a habit. ++ ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). ++ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). ++ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~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. ++ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). ++ ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). ++ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). ++ ~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). + ** Functions / Macros *** Macro: ~org-ql~ @@ -143,26 +169,6 @@ If ~NARROW~ is non-nil, buffers are not widened. ~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~, and ~priority~. -** Predicates - -Arguments are listed next to predicate names, when applicable. - -+ ~category (categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). -+ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~date (&optional comparator target-date)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. -+ ~habit~ :: Return non-nil if entry is a habit. -+ ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). -+ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). -+ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~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. -+ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). -+ ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). -+ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~tags (tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). -+ ~todo (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). - * Notes ** Comparison with Org Agenda searches @@ -200,15 +206,18 @@ Generates the predicate subtree. #+BEGIN_SRC elisp (defun org-ql--readme-predicate-list () "Return an Org list string documenting predicates." - (concat "Arguments are listed next to predicate names, when applicable.\n\n" + (concat (unpackaged/docstring-to-org + "Arguments are listed next to predicate names, when applicable. + + Note that, for convenience, standard numeric comparator function symbols (`<', `=', etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation.\n\n") (s-join "\n" (->> org-ql-predicates (--sort (string< (symbol-name (plist-get it :name)) (symbol-name (plist-get other :name)))) (--map (-let* (((&plist :name name :docstring docstring :fn fn) it) (args (->> (help-function-arglist fn) - (--remove (or (eq it '&rest) - ;; Comparing the symbol itself doesn't work for some reason. - (string= (symbol-name it) "--cl-rest--")))))) + (--replace-where (eq it '&rest) '&optional) + ;; Comparing the `--cl-rest--' symbol itself doesn't work for some reason. + (--remove (string= (symbol-name it) "--cl-rest--"))))) (if docstring (progn (setq docstring (s-replace "\n" " " docstring)) @@ -236,5 +245,5 @@ Generates the predicate subtree. (defun org-ql--readme-update-predicates () "Update predicate subtree in current document." (interactive) - (org-ql--readme-replace-node '("Usage" "Predicates") (org-ql--readme-predicate-list))) + (org-ql--readme-replace-node '("Usage" "Queries" "Predicates") (org-ql--readme-predicate-list))) #+END_SRC From ca22b7a9e19011dd5da320d29cf6ebff12cd2790 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 04:47:22 -0500 Subject: [PATCH 148/970] Docs: Add LICENSE --- LICENSE | 674 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 674 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. From 8ee5c2d131bb713f84e1ab8d1fc78d5c6e5f5929 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 04:50:55 -0500 Subject: [PATCH 149/970] Docs: Add ToC --- README.org | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index 670864d..cb7789e 100644 --- a/README.org +++ b/README.org @@ -2,6 +2,18 @@ ~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). +* Contents +:PROPERTIES: +:TOC: this +:END: + - [[#examples][Examples]] + - [[#usage][Usage]] + - [[#commands][Commands]] + - [[#queries][Queries]] + - [[#predicates][Predicates]] + - [[#functions--macros][Functions / Macros]] + - [[#notes][Notes]] + * Examples More examples are available in [[examples.org]]. @@ -35,10 +47,12 @@ More examples are available in [[examples.org]]. (property "composer" "Chopin") (not (property "key")))) #+END_SRC - * Usage ** Commands +:PROPERTIES: +:TOC: ignore-children +:END: *** org-ql-search @@ -134,6 +148,9 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~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). ** Functions / Macros +:PROPERTIES: +:TOC: ignore-children +:END: *** Macro: ~org-ql~ @@ -170,6 +187,9 @@ If ~NARROW~ is non-nil, buffers are not widened. ~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~, and ~priority~. * Notes +:PROPERTIES: +:TOC: ignore-children +:END: ** Comparison with Org Agenda searches @@ -192,10 +212,18 @@ But with ~org-ql-agenda~, you would write: This package is used by [[https://github.com/alphapapa/org-sidebar][org-sidebar]], which presents a customizable agenda-like view in a sidebar window. * License +:PROPERTIES: +:TOC: ignore +:END: GPLv3 -* Code :noexport: +* COMMENT Code :noexport: +:PROPERTIES: +:TOC: ignore +:END: + +# The COMMENT keyword prevents GitHub's renderer from showing this entry. Code used to update this document. @@ -247,3 +275,10 @@ Generates the predicate subtree. (interactive) (org-ql--readme-replace-node '("Usage" "Queries" "Predicates") (org-ql--readme-predicate-list))) #+END_SRC + +** File-local variables + +# Local Variables: +# eval: (require 'org-make-toc) +# before-save-hook: org-make-toc +# End: From a1b64f9eec0c29af35296dae275f3c80d869c793 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 05:00:20 -0500 Subject: [PATCH 150/970] Docs: Tidy --- README.org | 104 +++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/README.org b/README.org index cb7789e..76e1ab3 100644 --- a/README.org +++ b/README.org @@ -47,6 +47,7 @@ More examples are available in [[examples.org]]. (property "composer" "Chopin") (not (property "key")))) #+END_SRC + * Usage ** Commands @@ -64,9 +65,58 @@ Here's an example of using it to generate an agenda-like view for certain files [[images/org-ql-search-snippet.png]] -*** org-ql-agenda +** Queries -Also included is ~org-ql-agenda~, which uses ~org-ql~ queries to select entries and present them in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: +A 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. + +*** Predicates + +Arguments are listed next to predicate names, when applicable. + +Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation. + ++ ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). ++ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~date (&optional comparator target-date &optional)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. ++ ~habit~ :: Return non-nil if entry is a habit. ++ ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). ++ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). ++ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~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. ++ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). ++ ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). ++ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). ++ ~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). + +** Functions / Macros +:PROPERTIES: +:TOC: ignore-children +:END: + +*** Macro: ~org-ql~ + +/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ + +Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. + +~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). + +~QUERY~ is an ~org-ql~ query sexp, unquoted. + +~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. + +~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. + +If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). + +If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. + +*** Macro: ~org-ql-agenda~ + +This macro is like ~org-ql~, but it presents matching entries in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: #+BEGIN_SRC elisp (org-ql-agenda "~/src/emacs/org-super-agenda/test/test.org" @@ -121,55 +171,6 @@ Here are some other examples: (closed = today)))) #+END_SRC -** Queries - -A 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. - -*** Predicates - -Arguments are listed next to predicate names, when applicable. - -Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation. - -+ ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). -+ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~date (&optional comparator target-date &optional)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. -+ ~habit~ :: Return non-nil if entry is a habit. -+ ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). -+ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). -+ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~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. -+ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). -+ ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). -+ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). -+ ~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). - -** Functions / Macros -:PROPERTIES: -:TOC: ignore-children -:END: - -*** Macro: ~org-ql~ - -/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ - -Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. - -~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). - -~QUERY~ is an ~org-ql~ query sexp, unquoted. - -~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. - -~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. - -If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). - -If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. - *** Function: ~org-ql-query~ /Arguments:/ ~(buffers-or-files query &key action narrow sort)~ @@ -186,6 +187,7 @@ If ~NARROW~ is non-nil, buffers are not widened. ~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~, and ~priority~. + * Notes :PROPERTIES: :TOC: ignore-children From 7b093bba30ce30b93047fdfefd748d40d0cd680a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 18:49:06 -0500 Subject: [PATCH 151/970] Fix: (--predicate-done) Refer to new pred name Fixes #24. Thanks to @xeijin for reporting. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 20667ec..8c4ac7c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -284,7 +284,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin (org-ql--defpredicate 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--todo-p org-done-keywords))) + (or (apply #'org-ql--predicate-todo org-done-keywords))) (org-ql--defpredicate tags (&rest tags) "Return non-nil if current heading has one or more of TAGS (a list of strings)." From f6d58fcf704cd70fe6e0e5392d326b2810a9e37a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 21:23:14 -0500 Subject: [PATCH 152/970] Docs: Update, etc. --- README.org | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/README.org b/README.org index 76e1ab3..ae3a58c 100644 --- a/README.org +++ b/README.org @@ -73,7 +73,7 @@ A query is a lisp form which may contain arbitrary lisp forms, as well as certai Arguments are listed next to predicate names, when applicable. -Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation. +Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation. + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). @@ -234,12 +234,29 @@ Code used to update this document. Generates the predicate subtree. #+BEGIN_SRC elisp + (defun org-ql--readme-update-predicates () + "Update predicate subtree in current document." + (interactive) + (org-ql--readme-replace-node '("Usage" "Queries" "Predicates") (org-ql--readme-predicate-list))) + + (defun org-ql--readme-replace-node (outline-path string) + "Replace contents of node at OUTLINE-PATH with STRING." + (org-with-wide-buffer + (-let* ((subtree-marker (org-find-olp outline-path t)) + ((_headline element) (progn + (goto-char subtree-marker) + (org-element-headline-parser (point-max)))) + ((&plist :contents-begin beg :contents-end end) element)) + (goto-char beg) + (delete-region (point) (1- end)) + (insert string "\n")))) + (defun org-ql--readme-predicate-list () "Return an Org list string documenting predicates." (concat (unpackaged/docstring-to-org "Arguments are listed next to predicate names, when applicable. - Note that, for convenience, standard numeric comparator function symbols (`<', `=', etc.) do not need to be quoted when passed as an argument to these predicates. See examples in documentation.\n\n") + Note that, for convenience, standard numeric comparator function symbols (`<', `=', etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation.\n\n") (s-join "\n" (->> org-ql-predicates (--sort (string< (symbol-name (plist-get it :name)) (symbol-name (plist-get other :name)))) @@ -256,28 +273,16 @@ Generates the predicate subtree. (format " %s" args) "") (unpackaged/docstring-to-org docstring))) - (warn "No docstring for: %s" name) + (when (s-prefix? "org-ql-" (symbol-name name)) + (warn "No docstring for: %s" name)) nil))) -non-nil)))) - - (defun org-ql--readme-replace-node (outline-path string) - "Replace contents of node at OUTLINE-PATH with STRING." - (org-with-wide-buffer - (-let* ((subtree-marker (org-find-olp outline-path t)) - ((_headline element) (progn - (goto-char subtree-marker) - (org-element-headline-parser (point-max)))) - ((&plist :contents-begin beg :contents-end end) element)) - (goto-char beg) - (delete-region (point) (1- end)) - (insert string "\n")))) - - (defun org-ql--readme-update-predicates () - "Update predicate subtree in current document." - (interactive) - (org-ql--readme-replace-node '("Usage" "Queries" "Predicates") (org-ql--readme-predicate-list))) #+END_SRC +*** TODO Use async + +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. + ** File-local variables # Local Variables: From 974acb0f4334f1a297f007e06192f39db9a63524 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 21:48:53 -0500 Subject: [PATCH 153/970] Docs: Reorganize --- README.org | 54 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/README.org b/README.org index ae3a58c..ed32ece 100644 --- a/README.org +++ b/README.org @@ -50,6 +50,18 @@ More examples are available in [[examples.org]]. * Usage +The functionality provided may be grouped by: + ++ Interactive commands :: ~org-ql-search~ ++ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-query~ (function), and ~org-ql-agenda~ (macro) + +Alternatively, they may be grouped by: + ++ Showing an agenda-like view :: ~org-ql-search~ (command), and ~org-ql-agenda~ (macro) ++ Returning a list of matches or acting on them :: ~org-ql~ (macro), and ~org-ql-query~ (function) + +Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. + ** Commands :PROPERTIES: :TOC: ignore-children @@ -96,25 +108,9 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ :TOC: ignore-children :END: -*** Macro: ~org-ql~ +*** Agenda-like views -/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ - -Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. - -~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). - -~QUERY~ is an ~org-ql~ query sexp, unquoted. - -~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. - -~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. - -If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). - -If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. - -*** Macro: ~org-ql-agenda~ +**** Macro: ~org-ql-agenda~ This macro is like ~org-ql~, but it presents matching entries in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: @@ -171,7 +167,9 @@ Here are some other examples: (closed = today)))) #+END_SRC -*** Function: ~org-ql-query~ +*** Listing / acting-on results + +**** Function: ~org-ql-query~ /Arguments:/ ~(buffers-or-files query &key action narrow sort)~ @@ -187,6 +185,24 @@ If ~NARROW~ is non-nil, buffers are not widened. ~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~, and ~priority~. +**** Macro: ~org-ql~ + +/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ + +Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. + +~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). + +~QUERY~ is an ~org-ql~ query sexp, unquoted. + +~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. + +~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. + +If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). + +If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. + * Notes :PROPERTIES: From 9deec36458531fe0ba85a05645f070a7491fb283 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 23:31:24 -0500 Subject: [PATCH 154/970] Fix: Require org-habit It would be optimal to avoid requiring it, but not worth the trouble. --- org-ql.el | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 8c4ac7c..9212d0c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -19,6 +19,7 @@ (require 'cl-lib) (require 'org) +(require 'org-habit) (require 'seq) (require 'dash) @@ -252,9 +253,7 @@ Or, when possible, fix the problem." (cl-case symbol ('done (unless org-done-keywords ;; NOTE: This check needs to be done from within the Org buffer being checked. - (error "Variable `org-done-keywords' is nil. Are you running this from an Org buffer?"))) - ('habit (unless (featurep 'org-habit) - (require 'org-habit)))))) + (error "Variable `org-done-keywords' is nil. Are you running this from an Org buffer?")))))) (cl-loop for elem in form if (consp elem) do (progn From 6c6bb2d572032ddfac7e94ede2e086f3667bf876 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 17 Sep 2018 22:25:40 -0500 Subject: [PATCH 155/970] Add: Clocked selector and supporting code --- org-ql.el | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index 9212d0c..476217f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -132,13 +132,28 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (_ ; Buffer or string (list buffers-or-files)))) (predicate (byte-compile `(lambda () - (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda - (= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,query)))) + ;; This is either really elegant or really ugly. Well, also + ;; possibly somewhere in-between. At the least, we should do + ;; this in a more flexible, abstracted way, but this will do + ;; for now. Most importantly, it works! + (cl-macrolet ((clocked (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' + ;; function, not another `clocked'. + `(org-ql--predicate-clocked :from ,from :to ,to))) + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,query))))) (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) @@ -261,8 +276,63 @@ Or, when possible, fix the problem." (org-ql--sanity-check-form (cdr elem))) else do (check elem)))) +(defun org-ql--parse-time-string (s &optional end) + "Return Unix timestamp by parsing timestamp string S. +Calls `parse-time-string' and fills in nil second, minute, and +hour values, then calls `float-time'. When END is non-nil, sets +empty time values to 23:59:59; otherwise, to 00:00:00." + ;; TODO: Also accept Unix timestamps. + (cl-macrolet ((fill-with (place value) + `(unless (nth ,place parsed-time) + (setf (nth ,place parsed-time) ,value)))) + (let ((parsed-time (parse-time-string s))) + (pcase end + ('nil (fill-with 0 0) + (fill-with 1 0) + (fill-with 2 0)) + (_ (fill-with 0 59) + (fill-with 1 59) + (fill-with 2 23))) + (float-time (apply #'encode-time parsed-time))))) + ;;;;; Predicates +(org-ql--defpredicate clocked (&key from to) + "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. + +If FROM, return non-nil if entry was clocked on or after FROM. +If TO, return non-nil if entry was clocked on or before TO. +If ON, return non-nil if entry was clocked on date ON. + +FROM, TO, and ON should be strings parseable by +`parse-time-string' but may omit the time value. + +Note: See macrolet in `org-ql-query' which pre-processes +arguments to this function, parsing timestamp strings into Unix +timestamps and accepting `:on' keyword." + ;; 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-query'. + (declare (advertised-calling-convention (&key from to on))) + ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. + (cl-macrolet ((next-timestamp () + `(when (re-search-forward org-clock-line-re end-pos t) + (org-element-property :value (org-element-context)))) + (test-timestamps (pred-form) + `(cl-loop for next-ts = (next-timestamp) + while next-ts + for beg = (float-time (org-timestamp--to-internal-time next-ts)) + for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + thereis ,pred-form))) + (save-excursion + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (next-timestamp)) + ((and from to) (test-timestamps (and (<= beg to) + (>= end from)))) + (from (test-timestamps (<= from end))) + (to (test-timestamps (<= beg to)))))))) + (org-ql--defpredicate 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)))) From b2e8b9cbfcb569cdbde0f4b0d9697452f0c98160 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 22:49:52 -0500 Subject: [PATCH 156/970] Fix: (--predicate-clocked) advertised-calling-convention --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 476217f..baec414 100644 --- a/org-ql.el +++ b/org-ql.el @@ -314,7 +314,7 @@ arguments to this function, parsing timestamp strings into Unix timestamps and accepting `:on' keyword." ;; 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-query'. - (declare (advertised-calling-convention (&key from to on))) + (declare (advertised-calling-convention (&key from to on) nil)) ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. (cl-macrolet ((next-timestamp () `(when (re-search-forward org-clock-line-re end-pos t) From 7fed9f43bf5cd5eb2867e5cb27c7b29d7c7f2eee Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 23:50:10 -0500 Subject: [PATCH 157/970] Fix: Requirements --- org-ql-agenda.el | 2 ++ org-ql.el | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 5cc58a5..b11fbf0 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -35,10 +35,12 @@ (require 'org) (require 'org-agenda) (require 'seq) +(require 'rx) (require 'org-ql) (require 'dash) +(require 's) ;;;; Variables diff --git a/org-ql.el b/org-ql.el index baec414..64c278b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: http://github.com/alphapapa/org-ql ;; Version: 0.1-pre -;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0")) +;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0") (s "1.12.0")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: @@ -21,6 +21,7 @@ (require 'org) (require 'org-habit) (require 'seq) +(require 'subr-x) (require 'dash) From 3d4ad1ab3603bde0883d39fbff3920d7474c9016 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 8 Jun 2019 23:50:25 -0500 Subject: [PATCH 158/970] Add: Tests, Makefile, Cask --- Cask | 8 +++++ Makefile | 4 +++ tests/data.org | 10 +++++++ tests/test-org-ql.el | 70 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 Cask create mode 100644 Makefile create mode 100644 tests/data.org create mode 100644 tests/test-org-ql.el diff --git a/Cask b/Cask new file mode 100644 index 0000000..a78c6fa --- /dev/null +++ b/Cask @@ -0,0 +1,8 @@ +(package-file "org-ql.el") + +(files "org-ql.el" "org-ql-agenda.el") + +(source melpa) + +(development + (depends-on "buttercup")) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d5edecf --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ +.PHONY: test + +test: + cask exec buttercup -L . diff --git a/tests/data.org b/tests/data.org new file mode 100644 index 0000000..ba9aede --- /dev/null +++ b/tests/data.org @@ -0,0 +1,10 @@ + + +* Data + +** Clocked + +*** Clocked from 2018-12-01 00:00 to 2018-12-10 23:59 +:LOGBOOK: +CLOCK: [2018-12-01 Sat 00:00]--[2018-12-10 Mon 23:59] => 239:59 +:END: diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el new file mode 100644 index 0000000..78d61ef --- /dev/null +++ b/tests/test-org-ql.el @@ -0,0 +1,70 @@ +;;; org-ql.el --- Tests for org-ql -*- lexical-binding: t; -*- + +;; Copyright (C) 2019 Adam Porter + +;; Author: Adam Porter + +;; 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 . + +;;; Commentary: + +;; + +;;; Code: + +;;;; Requirements + +(require 'org-ql) +(require 'org-ql-agenda) + +;;;; Variables + + + +;;;; Functions + +;;;; Tests + +(describe "org-ql" + (before-all + (setq test-buffer (find-file-noselect (concat default-directory "tests/data.org")))) + + (describe "Can select entries clocked..." + (it "...at any time" + (expect (org-ql test-buffer + (clocked) + :action (org-get-heading t t)) + :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) + (it "...after (:from) a timestamp" + (expect (org-ql test-buffer + (clocked :from "2018-11-10") + :action (org-get-heading t t)) + :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) + (it "...up to (:to) a timestamp" + (expect (org-ql test-buffer + (clocked :to "2018-12-30") + :action (org-get-heading t t)) + :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) + (it "...on a date" + (expect (org-ql test-buffer + (clocked :on "2018-12-02") + :action (org-get-heading t t)) + :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) + (it "...within a date range" + (expect (org-ql test-buffer + (clocked :from "2018-12-03" :to "2018-12-11") + :action (org-get-heading t t)) + :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))))) + +;;; org-ql.el ends here From 3a036c3efb1b9143a59690188ba47440c7144620 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 00:03:32 -0500 Subject: [PATCH 159/970] Fix: Predicate args in documentation --- README.org | 13 +++++++------ org-ql.el | 5 ++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.org b/README.org index ed32ece..15af222 100644 --- a/README.org +++ b/README.org @@ -88,8 +88,9 @@ Arguments are listed next to predicate names, when applicable. Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation. + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). ++ ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: See macrolet in ~org-ql-query~ which pre-processes arguments to this function, parsing timestamp strings into Unix timestamps and accepting `:on' keyword. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~date (&optional comparator target-date &optional)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + ~habit~ :: Return non-nil if entry is a habit. @@ -103,6 +104,7 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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). + ** Functions / Macros :PROPERTIES: :TOC: ignore-children @@ -276,11 +278,10 @@ Generates the predicate subtree. (s-join "\n" (->> org-ql-predicates (--sort (string< (symbol-name (plist-get it :name)) (symbol-name (plist-get other :name)))) - (--map (-let* (((&plist :name name :docstring docstring :fn fn) it) - (args (->> (help-function-arglist fn) - (--replace-where (eq it '&rest) '&optional) - ;; Comparing the `--cl-rest--' symbol itself doesn't work for some reason. - (--remove (string= (symbol-name it) "--cl-rest--"))))) + (--map (-let* (((&plist :name name :docstring docstring :fn fn :args args) it) + (args (->> args + (--replace-where (listp it) (car it)) + (--replace-where (eq '&rest it) '&optional)))) (if docstring (progn (setq docstring (s-replace "\n" " " docstring)) diff --git a/org-ql.el b/org-ql.el index 64c278b..4c28941 100644 --- a/org-ql.el +++ b/org-ql.el @@ -51,7 +51,7 @@ This list should not contain any duplicates.") (let ((fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) (pred-name (intern (symbol-name name)))) `(progn - (push (list :name ',pred-name :fn ',fn-name :docstring ,docstring) org-ql-predicates) + (push (list :name ',pred-name :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates) (cl-defun ,fn-name ,args ,docstring ,@body)))) (cl-defmacro org-ql (buffers-or-files query &key sort narrow markers @@ -298,7 +298,7 @@ empty time values to 23:59:59; otherwise, to 00:00:00." ;;;;; Predicates -(org-ql--defpredicate clocked (&key from to) +(org-ql--defpredicate clocked (&key from to on) "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. @@ -315,7 +315,6 @@ arguments to this function, parsing timestamp strings into Unix timestamps and accepting `:on' keyword." ;; 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-query'. - (declare (advertised-calling-convention (&key from to on) nil)) ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. (cl-macrolet ((next-timestamp () `(when (re-search-forward org-clock-line-re end-pos t) From f930cd40b5e64b6d3d6d80b347b3236cb12c4837 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 00:05:26 -0500 Subject: [PATCH 160/970] Docs: Tidy --- README.org | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index 15af222..c247123 100644 --- a/README.org +++ b/README.org @@ -83,7 +83,7 @@ A query is a lisp form which may contain arbitrary lisp forms, as well as certai *** Predicates -Arguments are listed next to predicate names, when applicable. +Arguments are listed next to predicate names, where applicable. Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation. @@ -104,7 +104,6 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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). - ** Functions / Macros :PROPERTIES: :TOC: ignore-children @@ -272,7 +271,7 @@ Generates the predicate subtree. (defun org-ql--readme-predicate-list () "Return an Org list string documenting predicates." (concat (unpackaged/docstring-to-org - "Arguments are listed next to predicate names, when applicable. + "Arguments are listed next to predicate names, where applicable. Note that, for convenience, standard numeric comparator function symbols (`<', `=', etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation.\n\n") (s-join "\n" (->> org-ql-predicates From 4174dbad84ae6382674f922ba386d0acdcc7a15d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 00:08:26 -0500 Subject: [PATCH 161/970] Tidy: Docstring --- README.org | 2 +- org-ql.el | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index c247123..d6cc25f 100644 --- a/README.org +++ b/README.org @@ -88,7 +88,7 @@ Arguments are listed next to predicate names, where applicable. Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation. + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). -+ ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: See macrolet in ~org-ql-query~ which pre-processes arguments to this function, parsing timestamp strings into Unix timestamps and accepting `:on' keyword. ++ ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). diff --git a/org-ql.el b/org-ql.el index 4c28941..538d130 100644 --- a/org-ql.el +++ b/org-ql.el @@ -310,9 +310,9 @@ If ON, return non-nil if entry was clocked on date ON. FROM, TO, and ON should be strings parseable by `parse-time-string' but may omit the time value. -Note: See macrolet in `org-ql-query' which pre-processes -arguments to this function, parsing timestamp strings into Unix -timestamps and accepting `:on' keyword." +Note: Clock entries are expected to be clocked out. Currently +clocked entries (i.e. with unclosed timestamp ranges) are +ignored." ;; 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-query'. ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. From 3a10fe593db77c2b76616c441739838e46f7fdff Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 00:09:32 -0500 Subject: [PATCH 162/970] Docs: Fix argument name --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index d6cc25f..4d3c393 100644 --- a/README.org +++ b/README.org @@ -188,7 +188,7 @@ If ~NARROW~ is non-nil, buffers are not widened. **** Macro: ~org-ql~ -/Arguments:/ ~(buffers-or-files pred-body &key sort narrow markers action)~ +/Arguments:/ ~(buffers-or-files query &key sort narrow markers action)~ Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. From 943bb6d6c0d09d782b405c1338aeccd7cbaf5466 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 02:26:41 -0500 Subject: [PATCH 163/970] Add: (ts) predicates, improved tests --- README.org | 4 +- org-ql.el | 297 ++++++++++++++++++------ tests/data.org | 528 ++++++++++++++++++++++++++++++++++++++++++- tests/test-org-ql.el | 283 ++++++++++++++++++++--- 4 files changed, 1005 insertions(+), 107 deletions(-) diff --git a/README.org b/README.org index 4d3c393..a996110 100644 --- a/README.org +++ b/README.org @@ -90,7 +90,6 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + ~habit~ :: Return non-nil if entry is a habit. @@ -103,6 +102,9 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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). ++ ~ts (&key from to on)~ :: 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. ++ ~ts-active (&key from to on)~ :: Return non-nil if current entry has an active timestamp in given period. If no arguments are specified, return non-nil if entry has any active timestamp. If ~FROM~, return non-nil if entry has an active timestamp on or after ~FROM~. If ~TO~, return non-nil if entry has an active timestamp on or before ~TO~. If ~ON~, return non-nil if entry has an active timestamp on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. ++ ~ts-inactive (&key from to on)~ :: Return non-nil if current entry has an inactive timestamp in given period. If no arguments are specified, return non-nil if entry has any inactive timestamp. If ~FROM~, return non-nil if entry has an inactive timestamp on or after ~FROM~. If ~TO~, return non-nil if entry has an inactive timestamp on or before ~TO~. If ~ON~, return non-nil if entry has an inactive timestamp on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. ** Functions / Macros :PROPERTIES: diff --git a/org-ql.el b/org-ql.el index 538d130..8f5d842 100644 --- a/org-ql.el +++ b/org-ql.el @@ -46,7 +46,7 @@ This list should not contain any duplicates.") (cl-defmacro org-ql--defpredicate (name args docstring &rest body) "FIXME: docstring" - (declare (debug (symbolp listp stringp body)) + (declare (debug (symbolp listp stringp def-body)) (indent defun)) (let ((fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) (pred-name (intern (symbol-name name)))) @@ -137,24 +137,59 @@ a list of defined `org-ql' sorting methods: `date', `deadline', ;; possibly somewhere in-between. At the least, we should do ;; this in a more flexible, abstracted way, but this will do ;; for now. Most importantly, it works! - (cl-macrolet ((clocked (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' - ;; function, not another `clocked'. - `(org-ql--predicate-clocked :from ,from :to ,to))) - (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda - (= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,query))))) + (let (from to on) + ;; TODO: DRY these macrolets. + (cl-macrolet ((clocked (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' + ;; function, not another `clocked'. + `(org-ql--predicate-clocked :from ,from :to ,to)) + (ts (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts :from ,from :to ,to)) + (ts-active (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-active :from ,from :to ,to)) + (ts-inactive (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-inactive :from ,from :to ,to))) + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,query)))))) (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) @@ -446,6 +481,127 @@ comparator, PRIORITY should be a priority string." ;; Check that PROPERTY has VALUE (string-equal value (org-entry-get (point) property 'selective))))))) +;;;;;; Timestamps + +;; TODO: DRY these ts predicates. + +(org-ql--defpredicate ts (&key from to on) + "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-query'. + ;; 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) + (save-excursion + (goto-char (match-beginning 0)) + (org-element-timestamp-parser)))) + (test-timestamps (pred-form) + `(cl-loop for next-ts = (next-timestamp) + while next-ts + for beg = (float-time (org-timestamp--to-internal-time next-ts)) + for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + thereis ,pred-form))) + (save-excursion + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (next-timestamp)) + ((and from to) (test-timestamps (and (<= beg to) + (>= end from)))) + (from (test-timestamps (<= from end))) + (to (test-timestamps (<= beg to)))))))) + +(org-ql--defpredicate ts-active (&key from to on) + "Return non-nil if current entry has an active timestamp in given period. +If no arguments are specified, return non-nil if entry has any +active timestamp. + +If FROM, return non-nil if entry has an active timestamp on or +after FROM. + +If TO, return non-nil if entry has an active timestamp on or +before TO. + +If ON, return non-nil if entry has an active 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-query'. + ;; 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) + (save-excursion + (goto-char (match-beginning 0)) + (org-element-timestamp-parser)))) + (test-timestamps (pred-form) + `(cl-loop for next-ts = (next-timestamp) + while next-ts + when (string-prefix-p "<" next-ts) + for beg = (float-time (org-timestamp--to-internal-time next-ts)) + for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + thereis ,pred-form))) + (save-excursion + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (next-timestamp)) + ((and from to) (test-timestamps (and (<= beg to) + (>= end from)))) + (from (test-timestamps (<= from end))) + (to (test-timestamps (<= beg to)))))))) + +(org-ql--defpredicate ts-inactive (&key from to on) + "Return non-nil if current entry has an inactive timestamp in given period. +If no arguments are specified, return non-nil if entry has any +inactive timestamp. + +If FROM, return non-nil if entry has an inactive timestamp on or +after FROM. + +If TO, return non-nil if entry has an inactive timestamp on or +before TO. + +If ON, return non-nil if entry has an inactive 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-query'. + ;; 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) + (save-excursion + (goto-char (match-beginning 0)) + (org-element-timestamp-parser)))) + (test-timestamps (pred-form) + `(cl-loop for next-ts = (next-timestamp) + while next-ts + when (string-prefix-p "[" next-ts) + for beg = (float-time (org-timestamp--to-internal-time next-ts)) + for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + thereis ,pred-form))) + (save-excursion + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (next-timestamp)) + ((and from to) (test-timestamps (and (<= beg to) + (>= end from)))) + (from (test-timestamps (<= from end))) + (to (test-timestamps (<= beg to)))))))) + ;;;;; Date comparison (defun org-ql--date-type-p (type &optional comparator target-date) @@ -527,57 +683,58 @@ COMPARATOR should be a function (like `<=')." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :closed comparator target-date)) -(org-ql--defpredicate date (&optional comparator target-date (type 'active)) - "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. -Checks all Org-formatted timestamp strings in entry. TYPE may be -`active', `inactive', or `all', to control whether active, -inactive, or all timestamps are checked. Ranges of each type are -also checked. TARGET-DATE should be a string parseable by -`date-to-day'. COMPARATOR should be a function (like `<=')." - ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. - (let* ((entry-timestamps (save-excursion - ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will - ;; likely cause the action function to fail. We could wrap the call to the predicate in - ;; `save-excursion', but that would do it even when not necessary, which would be slower. - (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) - collect (match-string 0))))) - (pcase comparator - ('nil (pcase type - ('all entry-timestamps) - ('active (cl-loop for timestamp in entry-timestamps - thereis (string-prefix-p "<" timestamp))) - ('inactive (cl-loop for timestamp in entry-timestamps - thereis (string-prefix-p "[" timestamp))) - (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) - ((pred functionp) - ;; TODO: Avoid computing target-day-number every time this is called. - ;; Probably need to make a lambda that has it already defined. - (let ((target-day-number (cl-typecase target-date - (null nil) ; Calculated later. - ;; Append time to target-date because `date-to-day' requires it. - (string (date-to-day (concat target-date " 00:00"))) - (integer target-date)))) - (cl-loop for timestamp in entry-timestamps - for date-element = (with-temp-buffer - ;; MAYBE: Replace with ts.el eventually. - ;; TODO: Parse the element in the re-search-forward loop. - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)) - for this-target-day-number = (or target-day-number - ;; FIXME: Not sure if it makes sense to check warning - ;; days for non-planning timestamps, but we'll try it. - (+ (org-get-wdays timestamp) (org-today))) - thereis (when (or (eq 'all type) - (member (org-element-property :type date-element) - (pcase type - ('active '(active active-range)) - ('inactive '(inactive inactive-range))))) - (funcall comparator (org-time-string-to-absolute - (org-element-timestamp-interpreter date-element 'ignore)) - this-target-day-number))))) - (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" - comparator target-date))))) +;; (org-ql--defpredicate date (&optional comparator target-date (type 'active)) +;; "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. +;; Checks all Org-formatted timestamp strings in entry. TYPE may be +;; `active', `inactive', or `all', to control whether active, +;; inactive, or all timestamps are checked. Ranges of each type are +;; also checked. TARGET-DATE should be a string parseable by +;; `date-to-day'. COMPARATOR should be a function (like `<=')." +;; ;; NOTE: I think the `ts' predicate obsoletes this, but I'm leaving it commented for now. +;; ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. +;; (let* ((entry-timestamps (save-excursion +;; ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will +;; ;; likely cause the action function to fail. We could wrap the call to the predicate in +;; ;; `save-excursion', but that would do it even when not necessary, which would be slower. +;; (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) +;; collect (match-string 0))))) +;; (pcase comparator +;; ('nil (pcase type +;; ('all entry-timestamps) +;; ('active (cl-loop for timestamp in entry-timestamps +;; thereis (string-prefix-p "<" timestamp))) +;; ('inactive (cl-loop for timestamp in entry-timestamps +;; thereis (string-prefix-p "[" timestamp))) +;; (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) +;; ((pred functionp) +;; ;; TODO: Avoid computing target-day-number every time this is called. +;; ;; Probably need to make a lambda that has it already defined. +;; (let ((target-day-number (cl-typecase target-date +;; (null nil) ; Calculated later. +;; ;; Append time to target-date because `date-to-day' requires it. +;; (string (date-to-day (concat target-date " 00:00"))) +;; (integer target-date)))) +;; (cl-loop for timestamp in entry-timestamps +;; for date-element = (with-temp-buffer +;; ;; MAYBE: Replace with ts.el eventually. +;; ;; TODO: Parse the element in the re-search-forward loop. +;; (insert timestamp) +;; (goto-char 0) +;; (org-element-timestamp-parser)) +;; for this-target-day-number = (or target-day-number +;; ;; FIXME: Not sure if it makes sense to check warning +;; ;; days for non-planning timestamps, but we'll try it. +;; (+ (org-get-wdays timestamp) (org-today))) +;; thereis (when (or (eq 'all type) +;; (member (org-element-property :type date-element) +;; (pcase type +;; ('active '(active active-range)) +;; ('inactive '(inactive inactive-range))))) +;; (funcall comparator (org-time-string-to-absolute +;; (org-element-timestamp-interpreter date-element 'ignore)) +;; this-target-day-number))))) +;; (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" +;; comparator target-date))))) ;;;;; Sorting diff --git a/tests/data.org b/tests/data.org index ba9aede..bdc664d 100644 --- a/tests/data.org +++ b/tests/data.org @@ -1,10 +1,528 @@ +#+TODO: TODO TODAY NEXT STARTED IN-PROGRESS UNDERWAY WAITING SOMEDAY MAYBE CHECK | DONE CANCELED +* Test data -* Data +Rather than using my personal agenda every time I want to take a screenshot, how about this. -** Clocked +Will try to open the agenda view as if it was [2017-07-05 Wed] -*** Clocked from 2018-12-01 00:00 to 2018-12-10 23:59 -:LOGBOOK: -CLOCK: [2018-12-01 Sat 00:00]--[2018-12-10 Mon 23:59] => 239:59 +** 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: + 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: + SCHEDULED: <2017-07-04 Tue 21:00> + + Not sure what his timezone is... + +*** TODO [#B] Take over Mars + +**** TODO Visit Mars :space:travel:planet: + DEADLINE: <2017-09-20 Wed -3m> + + Ah, the red planet... + +*** TODO [#C] Take over the moon + +**** WAITING Visit the moon :space:travel: + DEADLINE: <2017-08-27 Sun -2m> + :LOGBOOK: + - State "WAITING" from [2017-07-24 Mon 19:01] + :END: + + Just waiting on that callback from NASA... + +*** 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 + DEADLINE: <2017-07-10 Mon -1w> + +*** DONE [#B] Learn universal sign language +CLOSED: [2017-07-05 Wed 03:02] +:PROPERTIES: +:ID: 729de245-75fa-43b4-845a-57af61109485 +:END: +:LOGBOOK: +- CLOSING NOTE [2017-07-05 Wed 03:02] \\ + All done! +CLOCK: [2017-07-05 Wed 02:00]--[2017-07-05 Wed 03:02] => 1:02 +:END: + +** TODO Order a pizza :food:dinner: +SCHEDULED: <2017-07-05 Wed 18:00> +:PROPERTIES: +:Effort: 5 +:END: + +** 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: +DEADLINE: <2017-07-21 Fri -1m> + +** 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: +SCHEDULED: <2017-07-05 Wed> + +If I don't, the frobnicator will probably fall off halfway to Mars... + +Gotta buy one first, though. + +** Recurring +:PROPERTIES: +:agenda-group: recurring +:END: + +*** CHECK /r/emacs :website:Emacs: + DEADLINE: <2017-07-05 Wed +1w> + +*** TODO Shop for groceries :food:shopping:@town: + SCHEDULED: <2017-07-05 Wed +1w> + :PROPERTIES: + :Effort: 30 + :END: + +*** Sunrise/sunset + +%%(org-super-agenda--test-diary-sunrise) +%%(org-super-agenda--test-diary-sunset) + +** Ideas +:PROPERTIES: +:CATEGORY: ideas +:END: + +*** 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] + - State "MAYBE" from [2017-07-24 Mon 18:58] + :END: + + I mean, since no one has ever tried doing it before... + +*** 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 +(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 78d61ef..af09e93 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -26,45 +26,266 @@ ;;;; Requirements (require 'org-ql) -(require 'org-ql-agenda) ;;;; Variables - - ;;;; Functions +(defun org-ql-test-insert-result () + "FIXME: docstring" + (interactive) + (let* ((value (eval (elisp--preceding-sexp))) + (prefix (if (and value (listp value)) + "'" + ""))) + (insert " :to-equal " + prefix + (format "%S" value)))) + ;;;; Tests (describe "org-ql" - (before-all - (setq test-buffer (find-file-noselect (concat default-directory "tests/data.org")))) - (describe "Can select entries clocked..." - (it "...at any time" - (expect (org-ql test-buffer - (clocked) - :action (org-get-heading t t)) - :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) - (it "...after (:from) a timestamp" - (expect (org-ql test-buffer - (clocked :from "2018-11-10") - :action (org-get-heading t t)) - :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) - (it "...up to (:to) a timestamp" - (expect (org-ql test-buffer - (clocked :to "2018-12-30") - :action (org-get-heading t t)) - :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) - (it "...on a date" - (expect (org-ql test-buffer - (clocked :on "2018-12-02") - :action (org-get-heading t t)) - :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))) - (it "...within a date range" - (expect (org-ql test-buffer - (clocked :from "2018-12-03" :to "2018-12-11") - :action (org-get-heading t t)) - :to-equal '("Clocked from 2018-12-01 00:00 to 2018-12-10 23:59"))))) + (before-all + + (defun org-ql-test-org-get-heading () + ;; For Org 9.0.5. + (substring-no-properties (org-get-heading t t))) + (defun org-ql-test-org-get-heading () + ;; 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")) + 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))))) + + (describe "Predicates" + + (describe "(category)" + (it "without arguments" + (expect (length (org-ql test-buffer + (category) + :action (org-ql-test-org-get-heading))) + :to-equal num-headings)) + (it "with a category" + (expect (org-ql test-buffer + (category "ambition") + :action (org-ql-test-org-get-heading)) + :to-equal '("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 "(clocked)" + (it "without arguments" + (expect (org-ql test-buffer + (clocked) + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language"))) + (it ":from a timestamp" + (expect (org-ql test-buffer + (clocked :from "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (clocked :from "2017-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ":to a timestamp" + (expect (org-ql test-buffer + (clocked :to "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (clocked :to "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ":on a date" + (expect (org-ql test-buffer + (clocked :on "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (clocked :on "2018-12-02") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it "within a range (:from and :to)" + (expect (org-ql test-buffer + (clocked :from "2017-07-04" :to "2018-12-11") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (clocked :from "2017-07-06" :to "2018-12-11") + :action (org-ql-test-org-get-heading)) + :to-equal nil) + (expect (org-ql test-buffer + (clocked :from "2017-07-01" :to "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal nil))) + + (describe "(closed)" + (it "without arguments" + (expect (org-ql test-buffer + (closed) + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language"))) + (it "=" + (expect (org-ql test-buffer + (closed = "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed = "2019-06-09") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it "<" + ;; TODO: Figure out why these tests take about 8 times longer than the other comparators in the (closed) tests. + (expect (org-ql test-buffer + (closed < "2019-06-10") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed < "2017-06-10") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ">" + (expect (org-ql test-buffer + (closed > "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed > "2019-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ">=" + (expect (org-ql test-buffer + (closed >= "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed >= "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed >= "2017-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it "<=" + (expect (org-ql test-buffer + (closed <= "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal nil) + (expect (org-ql test-buffer + (closed <= "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")) + (expect (org-ql test-buffer + (closed <= "2017-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language")))) + + (describe "(deadline)" + (it "without arguments" + (expect (org-ql test-buffer + (deadline) + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) + (it "=" + (expect (org-ql test-buffer + (deadline = "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("/r/emacs")) + (expect (org-ql test-buffer + (deadline = "2019-06-09") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it "<" + (expect (org-ql test-buffer + (deadline < "2019-06-10") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (expect (org-ql test-buffer + (deadline < "2017-06-10") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ">" + ;; TODO: Figure out why these tests take much longer than e.g. the (deadline <) tests. + (expect (org-ql test-buffer + (deadline > "2017-07-04 00:00") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (expect (org-ql test-buffer + (deadline > "2019-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ">=" + (expect (org-ql test-buffer + (deadline >= "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (expect (org-ql test-buffer + (deadline >= "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) + (expect (org-ql test-buffer + (deadline >= "2017-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) + (expect (org-ql test-buffer + (deadline >= "2018-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it "<=" + (expect (org-ql test-buffer + (deadline <= "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal nil) + (expect (org-ql test-buffer + (deadline <= "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("/r/emacs")) + (expect (org-ql test-buffer + (deadline <= "2018-07-06") + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + + (describe "(ts)" + (it "without arguments" + (expect (org-ql test-buffer + (ts) + :action (org-ql-test-org-get-heading)) + :to-equal '("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"))) + (it ":from a timestamp" + ;; TODO: Figure out why these take longer than the other (ts) tests. + (expect (org-ql test-buffer + (ts :from "2017-01-01") + :action (org-ql-test-org-get-heading)) + :to-equal '("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")) + (expect (org-ql test-buffer + (ts :from "2019-06-08") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + (it ":to a timestamp" + (expect (org-ql test-buffer + (ts :to "2019-06-10") + :action (org-ql-test-org-get-heading)) + :to-equal '("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")) + (expect (org-ql test-buffer + (ts :to "2017-07-04") + :action (org-ql-test-org-get-heading)) + :to-equal '("Skype with president of Antarctica"))) + (it ":on a timestamp" + (expect (org-ql test-buffer + (ts :on "2017-07-05") + :action (org-ql-test-org-get-heading)) + :to-equal '("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")) + (expect (org-ql test-buffer + (ts :on "2019-06-09") + :action (org-ql-test-org-get-heading)) + :to-equal nil)) + ) + + ;; TODO: Other predicates. + )) ;;; org-ql.el ends here From c40eb050a9739ffb25169e2bdd1123fa12e55024 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 05:01:07 -0500 Subject: [PATCH 164/970] Notes: Add tasks --- org-ql.el | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 8f5d842..472afc3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -253,7 +253,12 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (cl-defun org-ql--select (&key predicate action narrow) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." - ;; Since the mappings are done at runtime, macros like `flet' can't be used, so we do it manually. + ;; Since the mappings are stored in the variable `org-ql-predicates', macros like `flet' + ;; can't be used, so we do it manually (this is same as the equivalent `flet' expansion). + ;; Mappings are stored in the variable because it allows predicates to be defined with a + ;; macro, which allows documentation to be easily generated for them. + + ;; MAYBE: Lift the `flet'-equivalent out of this function so it isn't done for each buffer. (let (orig-fns) (--each org-ql-predicates ;; Save original function mappings. @@ -483,7 +488,9 @@ comparator, PRIORITY should be a priority string." ;;;;;; Timestamps -;; TODO: DRY these ts predicates. +;; TODO: Move active/inactive into (ts) predicate, allowing the first arg to be either inactive/active +;; or the comparator. Using numeric comparators is more powerful, concise, and language-independent +;; than using from/to. Alternatively, add :before/:after, but I think the comparators are better. (org-ql--defpredicate ts (&key from to on) "Return non-nil if current entry has a timestamp in given period. @@ -739,6 +746,7 @@ COMPARATOR should be a function (like `<=')." ;;;;; Sorting ;; FIXME: These appear to work properly, but it would be good to have tests for them. +;; MAYBE: Add timestamp sorter. Could be slow in some cases, without clever caching of timestamps per-entry. (defun org-ql--sort-by (items predicates) "Return ITEMS sorted by PREDICATES. From 9b5004b436d8358cf4901a2abafcebc0302fd388 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 9 Jun 2019 14:34:38 -0500 Subject: [PATCH 165/970] Fix: Restore date predicate Need to deprecate with a warning and update examples before removing. Fixes #25. Closes #26. Thanks to @xeijin for reporting. --- org-ql.el | 104 +++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/org-ql.el b/org-ql.el index 472afc3..2383bb2 100644 --- a/org-ql.el +++ b/org-ql.el @@ -690,58 +690,58 @@ COMPARATOR should be a function (like `<=')." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :closed comparator target-date)) -;; (org-ql--defpredicate date (&optional comparator target-date (type 'active)) -;; "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. -;; Checks all Org-formatted timestamp strings in entry. TYPE may be -;; `active', `inactive', or `all', to control whether active, -;; inactive, or all timestamps are checked. Ranges of each type are -;; also checked. TARGET-DATE should be a string parseable by -;; `date-to-day'. COMPARATOR should be a function (like `<=')." -;; ;; NOTE: I think the `ts' predicate obsoletes this, but I'm leaving it commented for now. -;; ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. -;; (let* ((entry-timestamps (save-excursion -;; ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will -;; ;; likely cause the action function to fail. We could wrap the call to the predicate in -;; ;; `save-excursion', but that would do it even when not necessary, which would be slower. -;; (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) -;; collect (match-string 0))))) -;; (pcase comparator -;; ('nil (pcase type -;; ('all entry-timestamps) -;; ('active (cl-loop for timestamp in entry-timestamps -;; thereis (string-prefix-p "<" timestamp))) -;; ('inactive (cl-loop for timestamp in entry-timestamps -;; thereis (string-prefix-p "[" timestamp))) -;; (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) -;; ((pred functionp) -;; ;; TODO: Avoid computing target-day-number every time this is called. -;; ;; Probably need to make a lambda that has it already defined. -;; (let ((target-day-number (cl-typecase target-date -;; (null nil) ; Calculated later. -;; ;; Append time to target-date because `date-to-day' requires it. -;; (string (date-to-day (concat target-date " 00:00"))) -;; (integer target-date)))) -;; (cl-loop for timestamp in entry-timestamps -;; for date-element = (with-temp-buffer -;; ;; MAYBE: Replace with ts.el eventually. -;; ;; TODO: Parse the element in the re-search-forward loop. -;; (insert timestamp) -;; (goto-char 0) -;; (org-element-timestamp-parser)) -;; for this-target-day-number = (or target-day-number -;; ;; FIXME: Not sure if it makes sense to check warning -;; ;; days for non-planning timestamps, but we'll try it. -;; (+ (org-get-wdays timestamp) (org-today))) -;; thereis (when (or (eq 'all type) -;; (member (org-element-property :type date-element) -;; (pcase type -;; ('active '(active active-range)) -;; ('inactive '(inactive inactive-range))))) -;; (funcall comparator (org-time-string-to-absolute -;; (org-element-timestamp-interpreter date-element 'ignore)) -;; this-target-day-number))))) -;; (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" -;; comparator target-date))))) +(org-ql--defpredicate date (&optional comparator target-date (type 'active)) + "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. +Checks all Org-formatted timestamp strings in entry. TYPE may be +`active', `inactive', or `all', to control whether active, +inactive, or all timestamps are checked. Ranges of each type are +also checked. TARGET-DATE should be a string parseable by +`date-to-day'. COMPARATOR should be a function (like `<=')." + ;; TODO: Deprecate this with a warning, suggest using (ts) instead, and remove (date) from examples. + ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. + (let* ((entry-timestamps (save-excursion + ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will + ;; likely cause the action function to fail. We could wrap the call to the predicate in + ;; `save-excursion', but that would do it even when not necessary, which would be slower. + (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) + collect (match-string 0))))) + (pcase comparator + ('nil (pcase type + ('all entry-timestamps) + ('active (cl-loop for timestamp in entry-timestamps + thereis (string-prefix-p "<" timestamp))) + ('inactive (cl-loop for timestamp in entry-timestamps + thereis (string-prefix-p "[" timestamp))) + (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) + ((pred functionp) + ;; TODO: Avoid computing target-day-number every time this is called. + ;; Probably need to make a lambda that has it already defined. + (let ((target-day-number (cl-typecase target-date + (null nil) ; Calculated later. + ;; Append time to target-date because `date-to-day' requires it. + (string (date-to-day (concat target-date " 00:00"))) + (integer target-date)))) + (cl-loop for timestamp in entry-timestamps + for date-element = (with-temp-buffer + ;; MAYBE: Replace with ts.el eventually. + ;; TODO: Parse the element in the re-search-forward loop. + (insert timestamp) + (goto-char 0) + (org-element-timestamp-parser)) + for this-target-day-number = (or target-day-number + ;; FIXME: Not sure if it makes sense to check warning + ;; days for non-planning timestamps, but we'll try it. + (+ (org-get-wdays timestamp) (org-today))) + thereis (when (or (eq 'all type) + (member (org-element-property :type date-element) + (pcase type + ('active '(active active-range)) + ('inactive '(inactive inactive-range))))) + (funcall comparator (org-time-string-to-absolute + (org-element-timestamp-interpreter date-element 'ignore)) + this-target-day-number))))) + (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" + comparator target-date))))) ;;;;; Sorting From ab77cc1cb02e55bd59c450c7036e804fe28b53b1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 10 Jun 2019 16:48:51 -0500 Subject: [PATCH 166/970] Docs: Silence code block --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index a996110..2d7150e 100644 --- a/README.org +++ b/README.org @@ -252,7 +252,7 @@ Code used to update this document. Generates the predicate subtree. -#+BEGIN_SRC elisp +#+BEGIN_SRC elisp :results silent :exports code (defun org-ql--readme-update-predicates () "Update predicate subtree in current document." (interactive) From a74520c2231b74a6915b0e7d2f593834a9fc6014 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 10 Jun 2019 16:49:06 -0500 Subject: [PATCH 167/970] Docs: (deadline) Mention org-deadline-warning-days --- README.org | 3 ++- org-ql.el | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index 2d7150e..d43251b 100644 --- a/README.org +++ b/README.org @@ -90,7 +90,8 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~; or if omitted, it is determined automatically using ~org-deadline-warning-days~. ~COMPARATOR~ should be a function (like ~<=~). + ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + ~habit~ :: Return non-nil if entry is a habit. + ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). diff --git a/org-ql.el b/org-ql.el index 2383bb2..9dcff25 100644 --- a/org-ql.el +++ b/org-ql.el @@ -664,8 +664,10 @@ COMPARATOR should be a function (like `<=')." (org-ql--defpredicate deadline (&optional comparator target-date) "Return non-nil if entry's deadline compares with TARGET-DATE using COMPARATOR. -TARGET-DATE should be a string parseable by `date-to-day'. -COMPARATOR should be a function (like `<=')." +TARGET-DATE should be a string parseable by `date-to-day'; or if +omitted, it is determined automatically using +`org-deadline-warning-days'. COMPARATOR should be a +function (like `<=')." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries ;; that have any deadline. But the common case of wanting to select entries whose deadline is From 0aec8ec60395197b2ef2b885c216cf84286efed9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 10 Jun 2019 18:18:36 -0500 Subject: [PATCH 168/970] Add: Search buffer refreshing, header line, etc. --- README.org | 18 +++++- images/org-ql-search.gif | Bin 423732 -> 206597 bytes org-ql-agenda.el | 124 +++++++++++++++++++++++++++++---------- 3 files changed, 109 insertions(+), 33 deletions(-) diff --git a/README.org b/README.org index d43251b..80e38b5 100644 --- a/README.org +++ b/README.org @@ -69,7 +69,23 @@ Feedback on these APIs is welcome. Eventually, after being tested and polished, *** org-ql-search -The command =org-ql-search= prompts for a query, a list of buffers or files, and how to group and sort results. Without prefix, it searches the current buffer instead of prompting. Then it presents the results in an agenda-like view. +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~. + +Press =g= to refresh the results buffer. [[images/org-ql-search.gif]] diff --git a/images/org-ql-search.gif b/images/org-ql-search.gif index fd09ffa2abede867719756feb22f5f2369c58527..593dd09559e80f45b2f9f2631bf7a9b348867210 100644 GIT binary patch delta 200781 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 fkIwj<1pHOTR8{RO-u8 zS8ugFkZjfQzF46(Hz7$@pnc}DB*ks@Om+>KeSY6!BECtmmwgm#ax*9k%4kthcvSeK zCE@w&fOk1u^6j<{n1ecA*}ZE!$Cegf@HBQE8@v5|oqrB(Ps>^ZZZv0}U=kG1-XzAT zzu=Wo`r~bO@o{<2jGi||2{ff8Fk5P{Zc$5V;>)ePmLzkoc>A=*3iVWtM8@e68J~UY zf3)WR&@lV)$+jpmpv5w-r1O4*TKkV{buUh<{rGgYA~623wt9N+_q@D-*R#I2rafyi z5N8UxpLN0Q{>gve8}5JHI2;;U|Ya#+hr zy?9@X^y&5g?CkQFnJ1ssV_EB$p17~%OKJVuu>WV&YCbPbFO+-wP`}QcjYDvsSgyv7 zMz?L!Y}{={TLTmvn>j@FOdNZ99Xq(y_1<_ig&*&8*(G9<*jxXE&2q0-rnCuYd9jK zOAop1Qv7JqCB3Jk`seC;-IS9mHL6>^7T=mU!DZRjsgJu_G*x4oaupPL=4`*Mi)-45CC_^y`zi9cHTQ#y;iBFh%H7%#l2;Nv3umc4#j{kn;Q zlZwO7hDB!|dax|obFZ#RR5WYhmVi*diQ595xFtf$xP66oRY5^Ir(&wuGo}_8rjkemC3T1N3Z5JoD2w$EAcrQJavDr zF`uW>h6AmZ=N$q&B1#e~uLssHeJNg_kiCp^*^CsWWfD^ob}_L^ByenR47(>e<({R+ z#0|dbd4YY?ImtJ_6_Hbg)Dp95O#dgbdyR7}TXH1eR`Yr9@b8E&WFXdf}rU-1g`r{Fs#j+)f zqwR7PS_&NORJi>a%sW;7h2Ar({4m-5(?o8|#}k-39iBf?Iu|DBAEVOzY>qImc~`^D zZh?g}jK!yxzf|xuUl!sPp#h6fyPazYHI6cKAreBSNOD?=Ni*<>dQ=o<0ERf zy7g%G{t(J=3=Y~JxiH}5#vUQ1h=W(t1C~8`n{|2C_gu}HWnWgeozan4xOIKk^C$xy zfyBE79j63&jXKIqO0R}5KD}!GthRP--Zb%$c}`pM+$LQ06j^fEBw*89vpWHQXB{>2 zQhj!6<8Q9ZA@vW^gY$Ok@D)0K-Pd*e?Stz|KI&zzH{?QkuRZfRHeq{YzW2mex%n)= z-_BT;{bZMx=oC52=Q_s6d`vH9zxT5}82B$RaF$-$Av3q_Ga@!?7hYVmm3{k+4{TS= zj|uahong%9#y+$EU#QZbgJ*xnifk*Ksmks4%wp$e4h9>=4qVk)3 zyQI5r^>AIirkPX&US*e8agg_t>=WrLoShsNFAm;#n_=z#dbVSVg}mgBf`ZMHT;p3V zaOE{9iv9vY$36 zPcl;E3XM>_-(a93oy7Uw?85PTvMpVQKe2hTN$RcM@b5%*UyX{2vgS#(%txyBb5zuf zHBU}c*r;^dAi?pFkT7rE#>um6p7!}&Rk}ArXzIFt)n_IMb_Psx9 z7IQ667f#wd=b4SV)#a6b%A)EXD^8uWI)3w9#ih;jzU@)B`@Hge?WfK2|NT*SVCE8K z5!kYT%~r!nc-4h8LGOipwHhwUS{FNmw$v{Y+pFPbyy{|a(U!$>e>FUuwJuGZv}K8! zt)_E(>7}Wgwk*}F)$~c$x;*pJmStvpGrbNLUY`4D%W}KFngPvPR~D9q{NsCYfr-iO zLvNgo!eUERt&qi9S62pYT@@z!>W76@GAIL0c*b?xM&ZCjSv>Si&Y?&6rSi2X#R1M>#smZnz? z(gg(>$-%2{-~F_0d)nGJNrE44wHPUgESb^9<#IaUzR`A%o#$%x{2RS5JS+<1%isDg zjdxb`i=yqj@BPhlTdIBMuv`fHO^-b08b|hHePVmw)#}$getq%nsqOo|?ai-!*?s@- zr|tVo_Fi3IKV8|2Rk8l}?|z=*9fyVf9dEPMc_b(=aYRwguq(JHUU+`QQN6m2<&k%i zBrfkbwtMQwp4>H$Wu3*2TRtE6AEX zZp&TJIZ@Sl6=b2k;9gxJ50!;IIbJNk7A@X5%WFQne3{8)l@yJ}ryNm%FU`7_^UB*QnM1dprYVWY-B~apH!1i3YbWNN zpBguvnQH9beypVN(Yt>s_y7Ie^z$>%>b;^Il146>4?H+^o_Hl_giF`=@g3>fx4*uB zW^P(QdcnoO8;$H~hLTP(SCo!q{GW0ts`fvF>Vzg1M&}8f_Y)?!aNhpF-WJECdGKL4 zd*BcM%Ktq(96ObEL@Y{}HKDk#>;Dhc30+TR&G`8Do!N9S@xN%LB=1#*$hd0WpG_Q& z=QSLg^iQn}?`SjeWu7xJrfg+EeS_J`NA(Su4+%M-KJd zZ&^K0m~~~=W47JDe!X79TIk4Ezq2aqt=CeHT|BEMX}K`_HSPWBZ*s9<@f`6x69NU? zu5as>Tfx!!tKUFJPvlhTO1D+Z9KZ9Kyhtejx+%;onWts7Q;@2ug{sW@|&!< z#2Mj}yESM1;%b%_68p7Bc?&aV%}2J#3B@0rM7TE2o6TkJd;C(^>Yy}p774L_qY>>i}O-7i{h5E zJ=)LeeeXZi>uE7qdQ42PwqxpwRj2>YIMi!CEjdo0Xb0<@&-NP~!q*CHo%@(qn)T&$ zD_Nxz>vkD1J>2t#ZO!c;yBvHtQ&^D}|9*csu5a(dH0|6p3nuk?^%E;t3p&OB zt#0@!Hi=i@jeEndg$p>0ndYbKxMWFvWYe_yArz9hL0K&21h0Stc=MsfnT34iCl1SG z6)66@_xpiYKoHTh8+|BLtv{j}v@p0V@0X;6mhCLNd z!pAFQEMz8f+!5#y`+u>g)u%pCL3)kDJD*EEL8(sNsv(UI6&u?p?nq*Mp~azZr`UU4 zmw~Zp$~-59FZ{xMOD1$jG%zvkTxeDGxUZY#xN%4WgYcdW+#C}QWd=R&RqqfoT_yO~ zULj<^{}Uyti6R^=Iwb;13WvLXJ2vpF`pDvPE>NMo)y?xPDnX6spo->2j`rV6Pzz?V7b%K>~xPq+`{01_|l34 z7Oa<6vF0dnn*5vMlqRCkBFf>Cp%bH=yQ)KF?vdho+!q(=uhLLxzVdmV^_AzmKXx{i z-}@MOLxESfV4;ZA(-rRC3mFW4)PI)G|H7($O{2#{%&Gk1s-sfIjVhssg6BEx z)O2e7cwBHov4U3W%Ay3T3GM$pmpd40*}kth-}2+pqRRn}%uQ7jrnVW+xp^Vkh2_<; zwv0ofIx-zr?#o+SITo+^KjCPE>Lxc`g`#HmpIH&YNynu6f>-ZrXcmdM$k6zvbbW2< zsHoqo1!hdA$Sft`9sHo3B{c6zsJ@`{1zN))O{l5!5a0^a)DWyLWB>8Saj>{q-n)U zyWg%2uGbb2TP3=oE|s-}bvJ{yN3-;)+MBxfcL~fCsy`yV^M^81m$z`^ld^u-wey^E zDjDB-P1}A(QQzR<>gZouM|MuM?I>UG<(Bxwe4$Wcdg6QS3IEx?TV#Z07jM5cai`dl zb{e@ro`o|$pogz4{N8OvGFw^6SgUla(_W7clgcjyFM|dPPP1tdCPVRH3 zE2rrf7vtWVav?r5{_D_ck8$V7tfB4z|1ou;{MV}hq$SB(8cbtA7IAPZR$IslwJI)ra``pM*`!+;cl;;uZC$1&>mHj^vqhR9harEoO&y`DJUwVH3bzU^7 zbk+ZwH{6lcw|)I4?BsWO$IbcM;YMRg6NBCJpErKmRONkN&z&Og@xA({`u+KvxlVw3jNwR`Q8_c|J9dt z{eRxmZ~LD7zvim2Qsr^+*f$)4`<_cT@hv*v{NXzrLM}pK!K6{>Rz!y${3rK0W5&_nv)X-S_YQQ{S`4E1oj1 z-&ignU0z*(vRr^MLg3@~8lHzWoQ}1;6(ujz>;DH-{WxAPks&!vylQrOsorw_KM%^j zGgJyFR`!-xzHM)Knl8YtQCjf5T;+s-Ktx6N^Gd^x+MMg9`ZH>8O>eZjQ7@QLBYLC6 z$)e$Vy1@MJ^&S}lldd=EooI>q-tbesDlkK!$Gnv@vBkcAM{A5nYwVBKgcq%e7HtVT z>QXA&GG?@8z0ldWs4eeCb4+-R@+(cZAav#QapB%*^c zrTt&yjE=4y9d!}h8Am$0GCC$j7RjsUl(fU-@!gJtaxixnqK?tI`$-oU6Lz;%a#$3%gz;sjgK0#Dw>^4$}RoCLTk zS9H$d=$L<_r`w1xXp^bZ1MX!W%pU}KEdn{h4@%Yju(-y-ccX&k#U~zzPZpaNcs|wW z+sdKx(NO5Xf!+rTdQP8cKNry-t7K60LHo=nORoi-Cq0<1HS}#bQQzMGxWA%<=Yt1Z zD+6D*0{fi+Zj%GN96uxOE^dF;(f-Mzzbd0&=BK>VB-xH6QSr`+do?C3TOnLwG3jH3 z1mDT-OAI~Qp8q8HJh`eiGAb4Hef-fOwR58E&B@Oi`+uEa{nIh|ou4NsQC3n_Oe(+#&RHWnu52h6sy`eMP`xp1lWawv^IVGu*rT&BE zMuzTg1s1_bt!`!8T+4|M8sx(=r$y|XS~F8(p@+r7fG#agz5^G!(mr(E?U+`%gJ=5= z#;c9(2R1PBSqkt5%id$)^i*I;IKXVdX|=;*LiNq*i!4Q_{%C*VF>&$CS*#(m>Z>KV zKWyX>Tsdo#r^A|+?cE9zR}E+Hl62r`%G>vI_5sN`hb-qDiJWt+a?XjFb53#2*}HSj zxu0_`NY1@vIrmEB+-sF{t**>@{4b1A`64&}f;nfOvD~nn_at)Ov&wldX3jHRGWW@{ z!22`jJX|^NljZy`k@LS*&bK)-@A0#F4^DDF>YQKCAhm$WY5|MY9O(v@+X;O0IvLJh zbHDS!eVQlN)eFp4UuG;(;QfDczIBQ3^b(JgU#&P6Fw`^1pJwplIptob;;GD)#mnV6 zIc$M})M6v6#jK|kpC)kK4&Yl*lKyKMgR}sn?pB7P2fQL(&hJ||xDT-2o3Jo+n=@BJ z2*(FM_E28u`hXy9hKxB!7Q1d^*-FD9p=`a^_hO)_RINZ>ghm z!7|7uiRat23pOwsDe&!muB30>2g;o}Ir3ls+toV6liHXaqdjcyvSmJXG z;_f);J#FIPN{GF&b&2|~`8=<<3vR8NKWo*7td)>W5~fp@H62bz*ELbHq-(<@QforQd9M+twTK8hsI^(Rx7ONINxwXpCYDrm^v-_+i zd%74JUM=Ym%iw9K=WgD{WHll5@l@W9Un@dX zS(Ei*LBTF~7GaNN;=ba%)obwzTSPr#-jr_uRPb>iUCS+X|$&KVP+N-^p!D zLxWbUZLiwBeX`f~7irsTq<1u}UMIMELAimB#;*n30t*j)Te!K(YsnXuvu-|{Z!I!f zxJV^yk&IT#3nsn-tra)ET8g~d(Hy<2ep&RqH?tN`V+z<}7~*HT)L9@%_G@7IwP0bZ zP#)3Hu&$;4r$T;+tlRNno1zxGm&#I$(9O$d?>V)5&Y4}ya(^vjU6{l+aeY%4N5enY z%?+htfvdvKep_)aV6(&R z-AUM6U*pPS%MdaD)^6kIrMrGvKJwgk;P!8-2L+hsQvO1Nr_I5hk!}USin6B?W zXfrE)yY(6q=?!yO4E+K!qQsUywcg{kWQB=Opw6BnJ~~mY^{;0d{PDQlCZNX6H>d3I zKW~pVkpr5$H|c5%D06#V*w*>LgZ=%K_Sr2Ap=UCE?;Oj^aW1*Nc@^u9{FviqGIQc) zZ}F~SKHX?U!9y4bIR=XRxSm0?WZS}#N;hFvoRpVdF7r{&)QBdt2teJ z`_!g2r=F#pUh?%+&8gGRpPk+jb0+!Mk#^|=Rt2#S0=l&t&PW$5;^SI)MrENywDUm~ z0gey7*L=3llU{!2&6%2Ai&SoVUY+86LFcUIsU6pI&b*6Re7|7vD(M4m)#a6=XqwGx0hP)^6Q+K>|!As z?k_f{pG~=#w`y;p)$-C=&g_C~m3@yKJoWG5BGG+CN1f&7u2AevQLnvdBD>(-?v;Bt zTs+jnV9vW=#CrcZgH>C_R(@i=!aDbowd}>EQuT|N&#Y#9vufh4%X5ESzRh~ZwD#(^ znHTT=4x6~@l8rB4mes+IoJ*IxoX@5@tI1wbIkVBT*IA)wtBmy#^Dmc@buXp%Uaiob z|9#Jj7B0gLs}>6QZY)1`UNraG{}1aguz6*dT`^m-(DKP)X6Ylpt@fFV+~}~m;S_bF za_`OOGtXU<;H?+pS}pp4>&^zA^F0gNq|fGLZ@lJn>HmhD+kdhTUSm$~X}{>eZent4 z>D$d_SB~mPAIawAd)njta?h>SE4Sv%z4IjU`u& z--w!58I$6*`|efQdsfnSkKDa;FK6rYoO^S-?>)ME?{V+lce3}(e9qK=ioL(o`@Vz0&;MMJ$?Ki1aZdQ0yPlTs8O232qc?uIcveAgjq<*;S8J|I z?0dXY^oEe`g}-Z@|J#OYv##Lb4g6p4vsCcz;ux)m<}JGur9wU9ma4TbW%9j{?fZnA zVZ{vDCpQ0{F8g{(q4$u{+Q;T5Px?+>ee`>Ipy;BP+?R8FPjk$BHenSr7vq+cvp3XV z?fvIG;d#Qp=Sx(tp66N>y7pSY-1~>L<~{S;#oe>N<;`jT5iX3JnrxW-Xop84Bfe}cG|HVJokDp z-;1NYCvMl=N%M2w8hb28=FZbS$Ba|9@5;SZeD6)xo}7Jm>o;xW%@MYGx83*r8rgTZ z-@Po1S^LWB?(cnX@7j8vu3K|U_5-8+*4MEQj#b^`>HkpA_t2che6i}sMxT2E`yY$# zpO+u}Q6heh^!$$}bx+7O{?qgJ`Z$;8{)wOW74<*O=6x9F^3jj)_(Yq}>r@}|^fBnZ z|5U;IFx70I(fd~>{ddjo*GIXo|15w0GsC^Nm-pXkp8SI(xixj`obCOcCEs4G^nZR|`=@p9zLrzY^$yzW zIPYHjzxL{s{ym-Y_nZ8#zGXf2UnQFP;}4r!zL{N@iyr)Xe|zQR`)``wUG1$~?e%w+ zPwq=^tI$K*59jOuw(vc_IRAbL@7mq_oY%GYc0V;99>!H~67o3QLl6(!M2`!s<*yYj-qump)$5WPh<}ViDV< zl_mw}Ls<6KuT)}MzxctTi$8Y;sx!@V)|lryJM3-Lw%oh>TBXC^#q7#Uyw|#OgVWa4 zydVGleJx;cd{-T#xZ9kFk4eXRW$oKy$_<3osM!y3`+F3&y9vb$~ z%P?>i4gd05X{N=ejQ+G8^@XX7QZ0%rXVw2RJh9lns55OM>oTVFnV+p5xw=V-cNDsX zA5v-*-<pstItE1T_CTvWVAu!;SL_94tp#0vkm*p4yA)AFVHO72c*7G~)S_@!vm0A3`|svp z?Q2ZBD{RLl$Z;(=VEUz$GrW@=ik8oFS^Jbps^m}lAvagmQulE0$^|W1Z3zd&i_Xsd zq@b5|^Zi98@umZOqJ9&;T+n_~vEW|45Wm&IzMmmC{2BG8oi#~p-T1g^PLSDzra6&S zSCbaVI^MXrq}gWGjKgKtN^B~D+Hx6B8l~zi9!2tfi{NVE{1m1zMRD4Wz&|F1sj7{~ zjDjU}%l=I{8j)Xq=i>9^;-w-JBi4IKE&P)ua^ij)(>CYy+W$Ht3mbkby@;JH&Sw4Q zas3Vp_CDSef#u>xjzSveZ7pp)uNa(tv{RjR&4EeM`Ezav9-j2qts!Ug#dl8~CW?LZ zzrIubs=ML`*{~!Dz-&?J-S-m(gN8w2p z=Pv%rPVEzI{f0i7ttqMBFV{V4$(zf@(x+LjR=il0V^{HCC-%87BG$S+_}6yl+2!+X z>jJLq|8msYQ8y)fGMB5`zn<+5Y_pa{9^Q5DT)zrD0I(P~MQ^c0f zxys6Rg2`;51XsP&k_nQHHXkC_uH^aU5OC;!!G+ob7q0DO*>s5gf_};W14n0oh8GPK zI-He~oGe77SsFZCR4&bu)f3o|BAQa(qV>Qrq+n{**Qa*8EXfk0hnI2)<*KOO6#TNr zlx3L(tCn2K?Q;yrm;PJf%Xh=$f@9VsQKN0o_}vXBIk*V*PD-io6QA#Jx$axX@<2_-cAqq}%QMfnq?ydVxzqpG zrCHZwP9)TMnCQRZFl$|yTJPG|>031I@*FnKW22W zvkqsN8BXSOsgJ(6)-LEd>!#_0P4IYJb#SQsq~%#?xr_mammMTSWi7af}Ju ztGHuLjgf~ulY;fFvr5;tb%@G5xl$(o?`d$}y%|A1>(kYEa`l8)8sDwo_al1q9o_uu z*SYNzc3Zh5=f^EhT?@;ooIt%h#-ktBCw~>wDRYeXm*zf@X6$1#-Sz zs$?$4D4_@awqKEGgm3sZsdNriFbw<_Qk`h?ylmGb{q&!Y+TNX+(QxVJ`6n#P zQd>Ho^Y2rgq4VUk)BimguhT>thA~W=sn7 z+FjMG8FbS2Bdh7wjE7oLtNuOg&0QwQcs=i7zoThl%H~ktO-hxIFP&P~yZ6--tr-Rp z^{wH1Kb5XaxvRK{_0ww}#f+y`ODZm0JbZ8B-wld4ke4<793yeI-~LE-r^XB`rYe(I!EQU?kjusWLiNAS8Pe=wb;JTFCITG zyz}6aS=`>$ysxrLs-H}#jeB}&Zk{;LpFGCzv8?(G`M2&ypR0{6YkKp`qb0ri*-Ymz zzgpkDklp_K(rNdvsfqvkzWlBYU$&>D}|TYE;4MdDcmj5sT!snSta!O==+F+nx2NYjjSi!e$MWAN8jj6 zwSC>a8PY#)+bCa}yst#>YvIIiaf^Sq7EQJIZ~gB>Tj1C0I`fw;n3?lZYaXdYO#V83UV%BSK3cQzRBX4)Fk-M1%$JEr;ok57NS!)~6rr`3{IAJF@`H0|;M zp%}s3S3B~4v3p0G`g1$7GnxxeIVh}hP;$$`dxsB5UpW|l+VKPPw);D5cW@k%RdH(V zI@or@ENY_J)(>W0-DYYzb37{#DJ^k2BJppl+7xab8(!TthxBq({}cQ(!9ZCKjjbbIlhC#P5M)oPuut#fjd*0IQGvsY`+ z`s@;Tan*Cnj@!mNml__8naFfQ!SHA0%-fGSCw!0ym~td8gkzoX{L4kNeCqe?ea~ba zog}rjdFIKcnLc-BPB1)n)o9jfFOKjtR{aO(O;~s=ZO>8PH~g$hO=mV(#jChCd+hnP zYh%bK-NVYRvo+mb7fYT=UT3v&PT8C($8WE@?!4jAqdAo-yY2t&S@7nTUO3~nTyCfB zo(rUv=RVOo-Zn+@TC&aoK{uZ_Zj&y$N7o;k|KpND^qqdDX15BL4VgXiEgO!Re)3Si z;r2)2nD3N*hA%j`oc3tfaevjlSai3`)lUb?@9byeu;-gsJHP21Ua*8a6Gx-t})YhxOIeO7k3 zwDP-k{bqBmQ_fyXngvcX{oy*3>8)pcWM9SpohApiJ!Es0;Mj8IR9w%2mov5;bn&_J z;DBRt-(jCK$M^ImuiBz&!gsvo%;}mwsXZnFN6wrx>62@5rVe2o>O;q z&OJ!+V-c_@QFdN3WpP=f^utA)Oe{BAhBSU-KKvv{(V){=UHORe&J|K8PfJL0DtaC+ zxg+duv#QFb!|e)-OT_u_bAW?_iZC#>w z_N9B-6OWmS>-WwM-ult+_matrI48>ro;b0azv;;OrGJh$I(QVM1Yi4j-07?1{*bws z9fM6-gA*U`vDh`EM{!ou1G)E%^12?jlN;rkSc8@cUz*x@;^&IJ=NL~lS$GO~oqSm3 zDJse_ufTJ&hi%J*tKqFzubjT}o^!rOJ+Ij;otd1sc6h6H2w5r4Ip8HBEz0W4QD|+) zQM!Jg#G?6kY?~xbE&rp$_w@p|)D=%nmep5!Qbg@Je}>K7ZChx1P1-?`^Gm4P<5N#P z_n&w*$7zGI%_J3%U5&5*1fBXf)Basa=gb+`8Rkq?PuA4^Y%gqmp8L`1^&h+sh;SS< z>9|;5c%$|1Qj68fD>q#))7^T=XG_%O8~w4pg;rYpNb~l5qXv)E(29Z-* zZ*Gw|H)Cn!{TVlB9gXBLIUAPZ*&K29TFjM03q)9xIBq`aU3m7U{bbYoA&UGgejN`E zE%oqdtGKnj3izWZoGR-x!TXr$6R`@h%3tp z`Ge+n-^lEks=RZp=0hhJD;XD!-+uj4lUjHTMIJia@44-eBKAQ>*v3^;U69i(@%mob z8z2ANws5(1&^Man_4y#i3%!%C=hYsK*%=(c8~ac6fon?l(a26QuB&T&ZipRHJ?X1+ zmvgSz?c~5+m8%pD>!b5@W^hjxy|r}O!rHrMS~p0Fc6gP}JFj{-J4b#OYwWY53XwM_ zp3ORR-Y97G!YL62ZSp!C*(H}=+s;bS*>g_o_Vh|Ob%uDBOL6a1;|>c2AK0mPlyThx z-pv<7Pi;D2bLHsq6T*64AKPLYq<-d3pQIwSSwOGy&w|v??tg3bVqLWA|Fb@*&As0_ zD@5w7#M8a^!{>V4+`AykbzA6M5nkzATncPP0UbPf;*zVb>TBKa>#_ZJh+oi8LCEYO z=QiDhsS3S|SKVMeVcK;q>FEPgq3~UM!@iu|@Wt_#z|)&@ai=n;{#&ScZu5FwjzaAu z^=XL(BC*nDYsy_2j86$}SLJ3hIZ*$L)q!!z4FhNIZEyCQCvk1fxm)@5K!oVyT|6F5 zwv&FH-uyjy(a+u9U$#Crf7fquEvfU-4M(#lCs?*mw0+{5#y{29F@KSd+q5SWY!A83 z>-9W#bDgN^xg$?zxH?{7ej4y@#{=P~7fx=QuNt|t;_N(M-nkl2!`q%lOnVx+>}k}t zr_nsep2l2z8vE>N+_$IklXq%Z*B84zF9~~In)bZR?3v1mZ57j=S1x;Awe5NJzhlp9 zu05}P_Pp-f^Ln-y6=sa(dTG7}?8O?axnV3bG#UfqUeruuD&|NPzR}jAHmgJNMTXkb zq<=zr2ikhRrRKkAiW1A5^sXu7G1CSHu_QUMMF(4p8lFxOd+PIJq0R)hq-!mO63z7& z6x(x!+Il2jE@FHYuJCS!hoirW2`v|jDcydE-Y-!tw?psd39lBo3cjB z1<%=ilNlFvw$1&=9`E5$u%J1&skhJgHH**d zCdPR0+uN0FwnZB3lbV>L!(Ii&9#@vWAT599b8V^V6>7y_=RDx9;_BzSOrQ_DyX6Y;U-w-9Fast2pb(y@|yOm^Jr*{I)MI;N^}Y1~xH?7lk+2WbRM2 z|M525p#9lDMI(83WA|dcbVfak7tPB)&Cp<%`p-T?ZI;drLA~#9@*7@VIG7hu_o2`F zrBg?1&V$B)4AumT`g~P}X-0q9zp?dP`nPcQJnN}#ouBqOPmIf-*wxmnz~p^jQ1!r6 z3I3;!?5R6MgfCqF(%hXNc>cXCBe&uNVb%ZboZ@W$`5~U@7LUXl|a6Y;c`=DXSSvO=U%n_m+VBw744l7|Jkh+ z7~>0A#coWyaPaGz=cTLGvDLD3C;Vqu3D~~*_?O&+zb_P)C^GyAxBImuzG`KC{inXy zKQBann9aWTSbvf5ac<2Bwi)*sPMZJbvM>Gj&M#9+f?0S2+f=^RxCRM{^CdY7jZ*d5 zksNd5URbzJXpTG4l&;WN{eH*v>lLa$YNG!us@XqleE*?IebziN_WS?Z+kUn`w*Mi& z=~M10ruLa-TK6Zm8@^b4Pwln+=L?;6uj|#`z1rTfUN8G@|IfmPmP7n=-yi=O@NB`m zd%3-@U)4WobA8aXsJ!mPxmU;3-ej`d{5~6{zT!M5?IbK+``1N7`8MxjpVeG@{#jjI#FQt$YT;(~d4;jrAxZcX`toI~FDJFZ$#%m`gnf3-V zeUo<5e3Hhg67FUEyndc)dEAO{Jz2}=UH^hzHnJSP%26*m^;*QtMKZG<@5}q(r1#`q z>+Ob9E4CRvy6(i}tND=0XTgT$v4&i4PEYik^d@jC*Wr1#dS|BdM7K>*G@Me}d(_;m zU2DShYm=A`8>=)Kb_&FoEaB)8>y-}w(#t;6tx7TE6kCu^u`{Q_U*~3nn9P<1P396V zvm&qjO^z+Usk$+?zE&u*L@eM$Z^u+Op;-}vofka6&vVT+WSK5TZz=;yAhOqS@n;gBOgK&fO*@{_KLpZj+{O z=A5!LgFAHF1nqzwodT&+Ps95Pq9t~E z$G^?$&bn~!#-@{tK_&onN@OC8+UC{WqCc%sgYoC&&Z zu4=mvPMoOPDImXdf^nZF)6e>%zMWG$H{|Vh&I|D~`F}t$K;P-aByrExf{J{*Zcq8i z|4;roR}0I5WgLG}_x(Op>8Gs^IJ zTuqi3SbgT1(io|;W4bo)Ce;>$m#TmJug$U2nULyKV%ypA1xNeVOf9g$s<+4ClmHbzum_Fr^;kMr^`mm)wvBV zCM8?@E|^VhSNa!VDb$y|Jgi0~ccwG<*Uo_ZM^2rd68yj*Z8guG4cDdw&y@MwuX(4! zSZsfWvdE^uYp3@IUNl)7U$;>FXVeOTD8&g8HRq+hGw=W2(59kuu|eHm@o4xDbphXm z&frT7_3c3^EoRQS3Sm5s@&3n-Pk6KUO!(ZxotvsyE!gc^byePoMpJ( zV7n+jPwJRiAFnSq!7EX36LcGeuhXU^#-I*2ljWMHb0xgU1$`#(tEo*U3H>xm(PjfNjx7|os}0cWr=Np?4rmL z%2Q}k;O6jDT*TPJ9kGe!Y5*gX92a|6eHLUJh3LsHjwRX}+!+qlOG-UueVAD^rylkC zFL`;P(AIw|+(MJh<3C;OwRtbEv37}P;Hsc$a$8r0?bQm~I_b(!ovUj66P$JB0#3HO zl}HJTW`$i|b!{tO>1wmP9%dm6^sFK-vAlh`++g;~>yTX(+6m0vC--n|+t6mKsFNhT z`o>YSNgH|~+bB*3iB0KStCMED`sUf9ZJX!)oxY!)MY%q6XXl+y+qUm>eXCaX`}RYj z?K`IMt}EzWednps_4Oxw^NJU1-+lS*)6NS^^~yG{jtz31X=OpL? z8oT0mEM8kyTwE;FddTI}^aCbL(*?zCOR8?Zx^_J2yj+>}_x1PoPk%U#IiUW?QI(mU zD$7

eAWv;!(H3F^$JPCf72Q^B*pqq1nTbWYr*mUDb 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¬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%0DaW6^e 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 delta 392681 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 YlCUF#O5h;QM}!)xVz$ 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 X-|}pXMjIlMke*Y3>d^ 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 z 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 diff --git a/org-ql-agenda.el b/org-ql-agenda.el index b11fbf0..09f40e0 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -47,6 +47,13 @@ (defvar org-ql-agenda-buffer-name "*Org Agenda NG*" "Name of default `org-ql-agenda' buffer.") +;; For refreshing results buffers. +(defvar org-ql-buffers-files) +(defvar org-ql-query) +(defvar org-ql-sort) +(defvar org-ql-narrow) +(defvar org-ql-super-groups) + ;;;; Macros ;; FIXME: DRY these two macros. @@ -124,8 +131,13 @@ is used, rather than binding it locally." Interactively, prompt for these variables: BUFFERS-FILES: A list of buffers and/or files to search. -Interactively, may also be an expression which evaluates to such -a list. +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'. @@ -136,39 +148,47 @@ searching. Interactively, with prefix, leave narrowed. SORT: One or a list of `org-ql' sorting functions, like `date' or `priority'." (declare (indent defun)) - (interactive (progn - (when (and current-prefix-arg - (not (derived-mode-p 'org-mode))) - (user-error "Not an Org buffer: %s" (buffer-name))) - (list (--if-let (read-from-minibuffer "Buffers/Files (blank for current buffer): ") - ;; TODO: Add glob matching? Buffer mode matching? - (pcase it - ("" (current-buffer)) - ((rx bos "(") (-flatten (eval (read it)))) - (_ (s-split (rx (1+ space)) it))) - (current-buffer)) - (read-minibuffer "Query: ") - :narrow (eq current-prefix-arg '(4)) - :groups (pcase (completing-read "Group by: " - (cons "Don't group" - (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6)))) - ("Don't group" nil) - (property (list (list (intern (concat ":auto-" property)))))) - :sort (pcase (completing-read "Sort by: " - (list "Don't sort" - "date" - "deadline" - "priority" - "scheduled" - "todo")) - ("Don't sort" nil) - (sort (intern sort)))))) + (interactive (list (pcase-exhaustive (completing-read "Buffers/Files:" + (list 'buffer 'agenda 'all)) + ("agenda" (org-agenda-files)) + ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) + (buffer-list))) + ("buffer" (current-buffer)) + ((and form (guard (rx bos "("))) (-flatten (eval (read form)))) + (else (s-split (rx (1+ space)) else))) + (read-minibuffer "Query: ") + :narrow (eq current-prefix-arg '(4)) + :groups (pcase (completing-read "Group by: " + (cons "Don't group" + (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) + ("Don't group" nil) + (property (list (list (intern (concat ":auto-" property)))))) + :sort (pcase (completing-read "Sort by: " + (list "Don't sort" + "date" + "deadline" + "priority" + "scheduled" + "todo")) + ("Don't sort" nil) + (sort (intern sort))))) (org-ql-agenda--agenda buffers-files query :narrow narrow :sort sort - :super-groups groups)) + :super-groups groups + :buffer "*Org QL Search*")) + +(defun org-ql-search-refresh () + "Refresh current `org-ql-search' buffer." + (interactive) + (org-ql-agenda--agenda org-ql-buffers-files + org-ql-query + :sort org-ql-sort + :narrow org-ql-narrow + :super-groups org-ql-super-groups + :buffer (current-buffer))) ;;;; Functions @@ -191,14 +211,54 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) (t it)) (s-join "\n" it))) + (buffer (cl-etypecase buffer + (string (org-ql-agenda--buffer buffer)) + (null (org-ql-agenda--buffer buffer)) + (buffer buffer))) (inhibit-read-only t)) - (with-current-buffer (org-ql-agenda--buffer buffer) + (with-current-buffer buffer + ;; Prepare buffer, saving data for refreshing. + (setq-local org-ql-buffers-files buffers-files) + (setq-local org-ql-query query) + (setq-local org-ql-sort sort) + (setq-local org-ql-narrow narrow) + (setq-local org-ql-super-groups super-groups) + ;; TODO: Derive a minor mode and set keymap there. + (local-set-key "g" #'org-ql-search-refresh) + (let* ((query-formatted (format "%S" query)) + (query-formatted (propertize (org-ql-agenda--font-lock-string 'emacs-lisp-mode query-formatted) + 'help-echo query-formatted)) + (query-width (length query-formatted)) + (available-width (- (window-width) + (length "In: ") + (length "Query: ") + query-width 4)) + (buffers-files-formatted (format "%S" buffers-files)) + (buffers-files-formatted (propertize (->> buffers-files-formatted + (org-ql-agenda--font-lock-string 'emacs-lisp-mode) + (s-truncate available-width)) + 'help-echo buffers-files-formatted))) + (setq-local header-line-format (concat (propertize "Query: " 'face 'org-agenda-structure) + query-formatted " " + (propertize "In: " 'face 'org-agenda-structure) + buffers-files-formatted))) + ;; Clear buffer, insert entries, etc. (erase-buffer) (insert entries) (pop-to-buffer (current-buffer)) (org-agenda-finalize) (goto-char (point-min))))) +(defun org-ql-agenda--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... + (with-temp-buffer + (delay-mode-hooks + (insert s) + (funcall mode) + (font-lock-ensure) + (buffer-string)))) + (defun org-ql-agenda--buffer (&optional name) "Return Agenda NG buffer, creating it if necessary. If NAME is non-nil, return buffer by that name instead of using From 28fce8b871440a8d531b7e572e27f27aafc0cfd6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 20 Jun 2019 13:32:26 -0500 Subject: [PATCH 169/970] Tests: Add (done) --- tests/test-org-ql.el | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index af09e93..a718f9f 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -249,6 +249,12 @@ :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) + (it "(done)" + (expect (org-ql test-buffer + (done) + :action (org-ql-test-org-get-heading)) + :to-equal '("Learn universal sign language"))) + (describe "(ts)" (it "without arguments" (expect (org-ql test-buffer From a7d8018f6441bce1cf1c9d9e946b6a8bf8f31f10 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 2 Jul 2019 19:43:38 -0500 Subject: [PATCH 170/970] Notes: Add todo --- notes.org | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/notes.org b/notes.org index 16fd957..20c767e 100644 --- a/notes.org +++ b/notes.org @@ -4,6 +4,29 @@ ** TODO Update commentary +** TODO [#B] Implied string literal regexp selector + +As mentioned [[https://www.reddit.com/r/emacs/comments/c8e0zp/my_gnu_hyperbole_vision_quest_odyssey_two/esmtqow/][here]]: + +#+BEGIN_QUOTE markdown +> Third – The “StringFind” search tool seems to be busted currently, but it’s pretty killer when it works. Basically, it lets you do boolean searches through records, so entering: + +> `(and sonnet italian (not petrarch))` + +`helm-org-rifle` provides this, e.g. the equivalent query would be: + +`sonnet italian !petrarch` + +`org-ql` also provides a lispy way to do this, e.g.: + + (org-ql "poetry.org" + (and (regexp "sonnet") + (regexp "italian") + (not (regexp "petrarch")))) + +It is more verbose because of the explicit `regexp` selector, but it would be easy to add an implied string literal selector. Putting that on the to-do list now... ;) +#+END_QUOTE + ** TODO [#A] Tools for saving queries and accessing them *** TODO Save query from ql-agenda buffer From eb281fe34569901d84b502c1734d01cdb09246d8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 12:03:09 -0500 Subject: [PATCH 171/970] Release: 0.1 --- README.org | 11 +++++++++++ org-ql.el | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 80e38b5..98f6885 100644 --- a/README.org +++ b/README.org @@ -12,6 +12,7 @@ - [[#queries][Queries]] - [[#predicates][Predicates]] - [[#functions--macros][Functions / Macros]] + - [[#changelog][Changelog]] - [[#notes][Notes]] * Examples @@ -223,6 +224,16 @@ If ~NARROW~ is non-nil, query will run without widening the buffer (the default If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. +* Changelog +:PROPERTIES: +:TOC: ignore-children +:END: + +/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.1 + +First tagged release. * Notes :PROPERTIES: diff --git a/org-ql.el b/org-ql.el index 9dcff25..580722c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: http://github.com/alphapapa/org-ql -;; Version: 0.1-pre +;; Version: 0.1 ;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0") (s "1.12.0")) ;; Keywords: hypermedia, outlines, Org, agenda From 706832275725e4d875db0cabb1faa6b40b9f73a2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 12:36:52 -0500 Subject: [PATCH 172/970] Meta: Update version --- README.org | 4 ++++ org-ql.el | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 98f6885..a5a6dbd 100644 --- a/README.org +++ b/README.org @@ -231,6 +231,10 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to /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.2-pre + +Nothing new yet. + ** 0.1 First tagged release. diff --git a/org-ql.el b/org-ql.el index 580722c..13420ad 100644 --- a/org-ql.el +++ b/org-ql.el @@ -2,7 +2,7 @@ ;; Author: Adam Porter ;; Url: http://github.com/alphapapa/org-ql -;; Version: 0.1 +;; Version: 0.2-pre ;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0") (s "1.12.0")) ;; Keywords: hypermedia, outlines, Org, agenda From 7dcdc21ea14f784f8f10dd66e2d89933126f4c27 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 12:33:52 -0500 Subject: [PATCH 173/970] Change: (regexp) Accept multiple regexps --- README.org | 3 ++- org-ql.el | 8 +++++--- tests/test-org-ql.el | 12 ++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index a5a6dbd..b2693f6 100644 --- a/README.org +++ b/README.org @@ -233,7 +233,8 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to ** 0.2-pre -Nothing new yet. +*Changed* ++ ~(regexp)~ selector accepts multiple regexps to test. ** 0.1 diff --git a/org-ql.el b/org-ql.el index 13420ad..fc59f14 100644 --- a/org-ql.el +++ b/org-ql.el @@ -461,14 +461,16 @@ comparator, PRIORITY should be a priority string." "Return non-nil if entry is a habit." (org-is-habit-p)) -(org-ql--defpredicate regexp (regexp) - "Return non-nil if current entry matches REGEXP (a regexp string)." +(org-ql--defpredicate regexp (&rest regexps) + "Return non-nil if current entry matches one of REGEXPS (regexp strings)." (let ((end (or (save-excursion (outline-next-heading)) (point-max)))) (save-excursion (goto-char (line-beginning-position)) - (re-search-forward regexp end t)))) + (cl-loop for regexp in regexps + thereis (save-excursion + (re-search-forward regexp end t)))))) (org-ql--defpredicate heading (regexp) "Return non-nil if current entry's heading matches REGEXP (a regexp string)." diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index a718f9f..aa9807a 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -255,6 +255,18 @@ :action (org-ql-test-org-get-heading)) :to-equal '("Learn universal sign language"))) + (describe "(regexp)" + (it "with 1 argument" + (expect (org-ql test-buffer + (regexp "Take over") + :sort todo + :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (it "with 2 arguments" + (expect (org-ql test-buffer + (regexp "Take over" "pizza") + :sort todo + :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) + (describe "(ts)" (it "without arguments" (expect (org-ql test-buffer From 25ce89ca2cea3c15a11171f0f41aff09b779c1ee Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 12:34:20 -0500 Subject: [PATCH 174/970] Tests: Add/change convenience commands --- tests/test-org-ql.el | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index aa9807a..43dc296 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -34,13 +34,26 @@ (defun org-ql-test-insert-result () "FIXME: docstring" (interactive) - (let* ((value (eval (elisp--preceding-sexp))) - (prefix (if (and value (listp value)) - "'" - ""))) - (insert " :to-equal " - prefix - (format "%S" value)))) + (if-let* ((sexp (elisp--preceding-sexp)) + (correct-sexp-p (eq (car sexp) 'org-ql)) + (value (eval sexp)) + (prefix (if (and value (listp value)) + "'" + ""))) + (insert " :to-equal " + prefix + (format "%S" value)) + (user-error "Point must be after an `org-ql' form"))) + +(defun org-ql-test-show-result () + "Show `org-ql-agenda' for `org-ql' form." + (interactive) + (if-let* ((sexp (elisp--preceding-sexp)) + (correct-sexp-p (eq (car sexp) 'org-ql))) + (progn + (setf (car sexp) 'org-ql-agenda) + (eval sexp)) + (user-error "Point must be after an `org-ql' form"))) ;;;; Tests From 014e0f138884185a54118122e9b71da858958883 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 12:34:34 -0500 Subject: [PATCH 175/970] Tests: Add (todo) tests --- tests/test-org-ql.el | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 43dc296..80663ec 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -280,6 +280,25 @@ :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) + (describe "(todo)" + (it "without arguments" + ;; FIXME: This returns an item that is done, which is incorrect. + (expect (org-ql test-buffer + (todo) + :sort todo + :action (org-ql-test-org-get-heading)) :to-equal '("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"))) + (it "with 1 argument" + ;; FIXME: Figure out why this takes >10x longer than the other (todo) tests, according to Buttercup. + (expect (org-ql test-buffer + (todo "WAITING") + :sort todo + :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon"))) + (it "with 2 arguments" + (expect (org-ql test-buffer + (todo "WAITING" "SOMEDAY") + :sort todo + :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (describe "(ts)" (it "without arguments" (expect (org-ql test-buffer From 3adaf4e5fcd676a020a589a6ba70b32fc17070d2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 09:31:48 -0500 Subject: [PATCH 176/970] Change: (org-ql-query) Call --select-cached with query, not pred Since we will be pre-processing and modifying the query, the predicate may not correspond exactly to the query, so we should key the cache on the original query. --- org-ql.el | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/org-ql.el b/org-ql.el index fc59f14..36c3742 100644 --- a/org-ql.el +++ b/org-ql.el @@ -209,7 +209,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (--map (with-current-buffer it (unless (derived-mode-p 'org-mode) (user-error "Not an Org buffer: %s" (buffer-name))) - (org-ql--select-cached :predicate predicate :action action :narrow narrow))) + (org-ql--select-cached :query query :predicate predicate :action action :narrow narrow))) ;; Flatten items (-flatten-n 1)))) ;; Sort items @@ -230,27 +230,29 @@ a list of defined `org-ql' sorting methods: `date', `deadline', "Return results for ARGS and current buffer using cache." ;; MAYBE: Timeout cached queries. Probably not necessarily since they will be removed when a ;; buffer is closed, or when a query is run after modifying a buffer. - (if-let* ((buffer-cache (gethash (current-buffer) org-ql-cache)) - (query-cache (cadr buffer-cache)) - (modified-tick (car buffer-cache)) - (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) - (cached-result (gethash args query-cache))) - (pcase cached-result - ('org-ql-nil nil) - (_ cached-result)) - (let ((new-result (apply #'org-ql--select args))) - (cond ((or (not query-cache) - (not buffer-unmodified-p)) - (puthash (current-buffer) - (list (buffer-modified-tick) - (let ((table (make-hash-table :test 'org-ql-hash-test))) - (puthash args (or new-result 'org-ql-nil) table) - table)) - org-ql-cache)) - (t (puthash args (or new-result 'org-ql-nil) query-cache))) - new-result))) + (-let (((&plist :query query :action action :narrow narrow) args)) + (if-let* ((buffer-cache (gethash (current-buffer) org-ql-cache)) + (query-cache (cadr buffer-cache)) + (modified-tick (car buffer-cache)) + (buffer-unmodified-p (eq (buffer-modified-tick) modified-tick)) + (cache-key (list query action narrow)) + (cached-result (gethash cache-key query-cache))) + (pcase cached-result + ('org-ql-nil nil) + (_ cached-result)) + (let ((new-result (apply #'org-ql--select args))) + (cond ((or (not query-cache) + (not buffer-unmodified-p)) + (puthash (current-buffer) + (list (buffer-modified-tick) + (let ((table (make-hash-table :test 'org-ql-hash-test))) + (puthash args (or new-result 'org-ql-nil) table) + table)) + org-ql-cache)) + (t (puthash args (or new-result 'org-ql-nil) query-cache))) + new-result)))) -(cl-defun org-ql--select (&key predicate action narrow) +(cl-defun org-ql--select (&key predicate action narrow &allow-other-keys) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." ;; Since the mappings are stored in the variable `org-ql-predicates', macros like `flet' From 3933db460bd2519996cfee520c2bcd81087afd1e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 10:40:59 -0500 Subject: [PATCH 177/970] Add: Query preambles Notes: Mark preambles as done Docs: Add changelog entry --- README.org | 3 + notes.org | 79 +++++++++++++++++- org-ql.el | 231 ++++++++++++++++++++++++++++++++--------------------- 3 files changed, 223 insertions(+), 90 deletions(-) diff --git a/README.org b/README.org index b2693f6..07d9bbe 100644 --- a/README.org +++ b/README.org @@ -236,6 +236,9 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to *Changed* + ~(regexp)~ selector accepts multiple regexps to test. +*Internal* ++ Optimizations for some query selectors, e.g. =regexp= and =todo=. These can provide a significant improvement for some queries. See benchmarks in [[file:notes.org][notes.org]]. + ** 0.1 First tagged release. diff --git a/notes.org b/notes.org index 20c767e..66af1a3 100644 --- a/notes.org +++ b/notes.org @@ -48,7 +48,7 @@ This would be useful for having a menu of saved queries as Org links, or even bo ** TODO [#A] Store query for refreshing ql-agenda buffer -** UNDERWAY [#B] Dual matching with regexp and predicates +** DONE [#B] Dual matching with regexp and predicates :PROPERTIES: :ID: 39972bb5-fdd0-4754-93ba-c85796a67ccf :END: @@ -69,6 +69,83 @@ Only entries that contain the word =lisp= can be matches, and searching each ent 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-query ,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! + +** TODO 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 [#A] Publish to MELPA ** TODO Add more sorters? diff --git a/org-ql.el b/org-ql.el index 36c3742..dd0a4b5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -127,91 +127,93 @@ 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', and `priority'." (declare (indent defun)) - (let* ((sources (pcase buffers-or-files - (`nil (list (current-buffer))) - ((pred listp) buffers-or-files) - (_ ; Buffer or string - (list buffers-or-files)))) - (predicate (byte-compile `(lambda () - ;; This is either really elegant or really ugly. Well, also - ;; possibly somewhere in-between. At the least, we should do - ;; this in a more flexible, abstracted way, but this will do - ;; for now. Most importantly, it works! - (let (from to on) - ;; TODO: DRY these macrolets. - (cl-macrolet ((clocked (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' - ;; function, not another `clocked'. - `(org-ql--predicate-clocked :from ,from :to ,to)) - (ts (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts :from ,from :to ,to)) - (ts-active (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-active :from ,from :to ,to)) - (ts-inactive (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-inactive :from ,from :to ,to))) - (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda - (= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,query)))))) - (action (byte-compile action)) - ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. - ;; (org-use-tag-inheritance t) - ;; (org-trust-scanner-tags t) - (org-ql--today (org-today)) - (items (->> sources - ;; List buffers - (--map (cl-etypecase it - (buffer it) - (string (or (find-buffer-visiting it) - (when (file-readable-p it) - ;; It feels unintuitive that `find-file-noselect' returns - ;; a buffer if the filename doesn't exist. - (find-file-noselect it)) - (user-error "Can't open file: %s" it))))) - ;; Filter buffers (i.e. select items) - (--map (with-current-buffer it - (unless (derived-mode-p 'org-mode) - (user-error "Not an Org buffer: %s" (buffer-name))) - (org-ql--select-cached :query query :predicate predicate :action action :narrow narrow))) - ;; Flatten items - (-flatten-n 1)))) + (-let* ((sources (pcase buffers-or-files + (`nil (list (current-buffer))) + ((pred listp) buffers-or-files) + (_ ; Buffer or string + (list buffers-or-files)))) + ((query preamble-re) (org-ql--query-preamble query)) + (predicate (byte-compile `(lambda () + ;; This is either really elegant or really ugly. Well, also + ;; possibly somewhere in-between. At the least, we should do + ;; this in a more flexible, abstracted way, but this will do + ;; for now. Most importantly, it works! + (let (from to on) + ;; TODO: DRY these macrolets. + (cl-macrolet ((clocked (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' + ;; function, not another `clocked'. + `(org-ql--predicate-clocked :from ,from :to ,to)) + (ts (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts :from ,from :to ,to)) + (ts-active (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-active :from ,from :to ,to)) + (ts-inactive (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-inactive :from ,from :to ,to))) + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,query)))))) + (action (byte-compile action)) + ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. + ;; (org-use-tag-inheritance t) + ;; (org-trust-scanner-tags t) + (org-ql--today (org-today)) + (items (->> sources + ;; List buffers + (--map (cl-etypecase it + (buffer it) + (string (or (find-buffer-visiting it) + (when (file-readable-p it) + ;; It feels unintuitive that `find-file-noselect' returns + ;; a buffer if the filename doesn't exist. + (find-file-noselect it)) + (user-error "Can't open file: %s" it))))) + ;; Filter buffers (i.e. select items) + (--map (with-current-buffer it + (unless (derived-mode-p 'org-mode) + (user-error "Not an Org buffer: %s" (buffer-name))) + (org-ql--select-cached :query query :preamble-re preamble-re + :predicate predicate :action action :narrow narrow))) + ;; Flatten items + (-flatten-n 1)))) ;; Sort items (pcase sort (`nil items) @@ -226,6 +228,51 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) (sxhash-equal (prin1-to-string args)))) +(defvar org-ql-use-preamble t + ;; FIXME: Move or delete this defvar. + "Use query preambles to speed up searches. +May be disabled for debugging, benchmarks, etc.") + +(defun org-ql--query-preamble (query) + "Return (QUERY PREAMBLE) 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." + (if org-ql-use-preamble + (let (org-ql-preamble) + (cl-labels ((rec (element) + (or (when org-ql-preamble + ;; Only one preamble is allowed + element) + (pcase element + (`(or _) element) + (`(regexp . ,regexps) + (let* ((regexp (rx-to-string `(or ,@regexps)))) + (setq org-ql-preamble regexp) + ;; Return nil + nil)) + (`(todo . ,(and todo-keywords (guard todo-keywords))) + (let* ((regexps (--map (list 'regexp + (format org-heading-keyword-regexp-format it)) + todo-keywords)) + (regexp (rx-to-string `(or ,@regexps)))) + (setq org-ql-preamble regexp) + ;; Return nil + nil)) + (`(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 org-ql-preamble))) + (list query nil))) + (defun org-ql--select-cached (&rest args) "Return results for ARGS and current buffer using cache." ;; MAYBE: Timeout cached queries. Probably not necessarily since they will be removed when a @@ -252,7 +299,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (t (puthash args (or new-result 'org-ql-nil) query-cache))) new-result)))) -(cl-defun org-ql--select (&key predicate action narrow &allow-other-keys) +(cl-defun org-ql--select (&key preamble-re predicate action narrow &allow-other-keys) "Return results of mapping function ACTION across entries in current buffer matching function PREDICATE. If NARROW is non-nil, buffer will not be widened." ;; Since the mappings are stored in the variable `org-ql-predicates', macros like `flet' @@ -279,9 +326,15 @@ If NARROW is non-nil, buffer will not be widened." (goto-char (point-min)) (when (org-before-first-heading-p) (outline-next-heading)) - (cl-loop when (funcall predicate) - collect (funcall action) - while (outline-next-heading))))) + (cond (preamble-re (cl-loop when (and (when (re-search-forward preamble-re nil t) + (outline-back-to-heading 'invisible-ok) + t) + (funcall predicate)) + collect (funcall action) + while (outline-next-heading))) + (t (cl-loop when (funcall predicate) + collect (funcall action) + while (outline-next-heading))))))) (--each orig-fns ;; Restore original function mappings. (fset (plist-get it :name) (plist-get it :fn)))))) From 3b88b71b4167e7f180b71ee484380cbde0f73bbf Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 13:01:45 -0500 Subject: [PATCH 178/970] Fix: Unused variable warnings --- org-ql.el | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/org-ql.el b/org-ql.el index dd0a4b5..499ac7e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -393,7 +393,9 @@ empty time values to 23:59:59; otherwise, to 00:00:00." ;;;;; Predicates -(org-ql--defpredicate clocked (&key from to on) +(org-ql--defpredicate 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. "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. @@ -417,11 +419,13 @@ ignored." (test-timestamps (pred-form) `(cl-loop for next-ts = (next-timestamp) while next-ts - for beg = (float-time (org-timestamp--to-internal-time next-ts)) - for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + ;; Using `setf' instead of `for beg =` here prevents "unused lexical variable" warnings. + do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) + end (float-time (org-timestamp--to-internal-time next-ts 'end))) thereis ,pred-form))) (save-excursion - (let ((end-pos (org-entry-end-position))) + (let ((end-pos (org-entry-end-position)) + beg end) (cond ((not (or from to)) (next-timestamp)) ((and from to) (test-timestamps (and (<= beg to) (>= end from)))) @@ -545,11 +549,14 @@ comparator, PRIORITY should be a priority string." ;;;;;; Timestamps -;; TODO: Move active/inactive into (ts) predicate, allowing the first arg to be either inactive/active -;; or the comparator. Using numeric comparators is more powerful, concise, and language-independent -;; than using from/to. Alternatively, add :before/:after, but I think the comparators are better. +;; TODO: Move active/inactive into (ts) predicate, allowing the first arg to be either +;; inactive/active or the comparator. Using numeric comparators is more powerful, concise, +;; and language-independent than using from/to. Alternatively, add :before/:after, but I +;; think the comparators are better. Also consider using a macro to DRY these out. -(org-ql--defpredicate ts (&key from to on) +(org-ql--defpredicate 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. @@ -575,18 +582,21 @@ FROM, TO, and ON should be strings parseable by (test-timestamps (pred-form) `(cl-loop for next-ts = (next-timestamp) while next-ts - for beg = (float-time (org-timestamp--to-internal-time next-ts)) - for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) + end (float-time (org-timestamp--to-internal-time next-ts 'end))) thereis ,pred-form))) (save-excursion - (let ((end-pos (org-entry-end-position))) + (let ((end-pos (org-entry-end-position)) + beg end) (cond ((not (or from to)) (next-timestamp)) ((and from to) (test-timestamps (and (<= beg to) (>= end from)))) (from (test-timestamps (<= from end))) (to (test-timestamps (<= beg to)))))))) -(org-ql--defpredicate ts-active (&key from to on) +(org-ql--defpredicate ts-active (&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 an active timestamp in given period. If no arguments are specified, return non-nil if entry has any active timestamp. @@ -615,18 +625,21 @@ FROM, TO, and ON should be strings parseable by `(cl-loop for next-ts = (next-timestamp) while next-ts when (string-prefix-p "<" next-ts) - for beg = (float-time (org-timestamp--to-internal-time next-ts)) - for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) + end (float-time (org-timestamp--to-internal-time next-ts 'end))) thereis ,pred-form))) (save-excursion - (let ((end-pos (org-entry-end-position))) + (let ((end-pos (org-entry-end-position)) + beg end) (cond ((not (or from to)) (next-timestamp)) ((and from to) (test-timestamps (and (<= beg to) (>= end from)))) (from (test-timestamps (<= from end))) (to (test-timestamps (<= beg to)))))))) -(org-ql--defpredicate ts-inactive (&key from to on) +(org-ql--defpredicate ts-inactive (&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 an inactive timestamp in given period. If no arguments are specified, return non-nil if entry has any inactive timestamp. @@ -655,11 +668,12 @@ FROM, TO, and ON should be strings parseable by `(cl-loop for next-ts = (next-timestamp) while next-ts when (string-prefix-p "[" next-ts) - for beg = (float-time (org-timestamp--to-internal-time next-ts)) - for end = (float-time (org-timestamp--to-internal-time next-ts 'end)) + do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) + end (float-time (org-timestamp--to-internal-time next-ts 'end))) thereis ,pred-form))) (save-excursion - (let ((end-pos (org-entry-end-position))) + (let ((end-pos (org-entry-end-position)) + beg end) (cond ((not (or from to)) (next-timestamp)) ((and from to) (test-timestamps (and (<= beg to) (>= end from)))) From 6a968d212f1b7225e288cb34347cbd8deaa3a112 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 13:05:16 -0500 Subject: [PATCH 179/970] Docs: Update first paragraph --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 07d9bbe..f3675ca 100644 --- a/README.org +++ b/README.org @@ -1,6 +1,6 @@ #+TITLE: org-ql -~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and perform actions on them, such as collecting their parsed representation with ~org-element~ (the default action). +~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and return a list of them or perform actions on them. Commands are also provided which display a buffer with matching results, similar to an Org Agenda buffer. * Contents :PROPERTIES: From 0b7628c1f72d96e799eef7b9b4a213ef4003005b Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Fri, 12 Jul 2019 18:52:11 +0200 Subject: [PATCH 180/970] Fix: Byte-compile warnings Define some `org-super-agenda` symbols in case org-super-agenda is not installed. --- org-ql-agenda.el | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 09f40e0..bd3e15e 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -33,6 +33,7 @@ (require 'cl-lib) (require 'org) +(require 'org-element) (require 'org-agenda) (require 'seq) (require 'rx) @@ -42,6 +43,13 @@ (require 'dash) (require 's) +;;;; Compatibility + +(defvar org-super-agenda-auto-selector-keywords) +(defvar org-super-agenda-groups) +(defvar org-super-agenda-mode) +(declare-function org-super-agenda--group-items "org-super-agenda") + ;;;; Variables (defvar org-ql-agenda-buffer-name "*Org Agenda NG*" From adcb96cb1e2fb3a10acf0fb9a3c231d5585af30f Mon Sep 17 00:00:00 2001 From: Daniel Kraus Date: Fri, 12 Jul 2019 18:53:06 +0200 Subject: [PATCH 181/970] Fix: Compatibility with org>=9.2 The API for `org-get-tags-at` and `org-timestamp--to-internal-time` changed in org-mode version 9.2. Thanks to Ataias Pereira Reis (@ataias) and Daniel Kraus (@dakra). Closes #27. Closes #31. --- README.org | 3 +++ org-ql-agenda.el | 7 +++++-- org-ql.el | 10 ++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index f3675ca..698197d 100644 --- a/README.org +++ b/README.org @@ -236,6 +236,9 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to *Changed* + ~(regexp)~ selector accepts multiple regexps to test. +*Compatibility* ++ Fixes for compatibility with Org 9.2. (Thanks to [[https://github.com/ataias][Ataias Pereira Reis]] and [[https://github.com/dakra][Daniel Kraus]].) + *Internal* + Optimizations for some query selectors, e.g. =regexp= and =todo=. These can provide a significant improvement for some queries. See benchmarks in [[file:notes.org][notes.org]]. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index bd3e15e..c8d6074 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -50,6 +50,9 @@ (defvar org-super-agenda-mode) (declare-function org-super-agenda--group-items "org-super-agenda") +(when (version< org-version "9.2") + (defalias 'org-get-tags 'org-get-tags-at)) + ;;;; Variables (defvar org-ql-agenda-buffer-name "*Org Agenda NG*" @@ -328,8 +331,8 @@ Its property list should be the second item in the list, as returned by `org-ele (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-at' used the correct buffer automatically. - (org-get-tags-at marker (not org-use-tag-inheritance))) + ;; I wish `org-get-tags' used the correct buffer automatically. + (org-get-tags marker (not org-use-tag-inheritance))) ;; No marker found (warn "No marker found for item: %s" title) (org-element-property :tags element)) diff --git a/org-ql.el b/org-ql.el index 499ac7e..fd60870 100644 --- a/org-ql.el +++ b/org-ql.el @@ -25,6 +25,12 @@ (require 'dash) +;;;; Compatibility + +(when (version< org-version "9.2") + (defalias 'org-get-tags 'org-get-tags-at) + (defalias 'org-timestamp-to-time 'org-timestamp--to-internal-time)) + ;;;; Variables (defvar org-ql--today nil) @@ -457,8 +463,8 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin (org-ql--defpredicate tags (&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-at' for every heading, especially with inheritance. - (when-let ((tags-at (org-get-tags-at (point) (not org-use-tag-inheritance)))) + ;; to run `org-get-tags' for every heading, especially with inheritance. + (when-let ((tags-at (org-get-tags (point) (not org-use-tag-inheritance)))) (cl-typecase tags (null t) (otherwise (seq-intersection tags tags-at))))) From 2b267ad195f9bf725cd41c77b64f8f5a3396cf59 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 13:45:25 -0500 Subject: [PATCH 182/970] Fix: Depend on Emacs 26.1 for if-let* --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index fd60870..4a1af2d 100644 --- a/org-ql.el +++ b/org-ql.el @@ -3,7 +3,7 @@ ;; Author: Adam Porter ;; Url: http://github.com/alphapapa/org-ql ;; Version: 0.2-pre -;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0") (s "1.12.0")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.0") (s "1.12.0")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: From 04725bb90026bbd6b602c0971565ee32d628fcf9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 13:45:39 -0500 Subject: [PATCH 183/970] Tidy: Remove unused macro --- org-ql.el | 9 --------- 1 file changed, 9 deletions(-) diff --git a/org-ql.el b/org-ql.el index 4a1af2d..93edb60 100644 --- a/org-ql.el +++ b/org-ql.el @@ -100,15 +100,6 @@ buffer. In this case, ACTION should return an Org element." :narrow ,narrow :sort ',sort)) -(defmacro org-ql--flet (fns &rest body) - ;; FIXME: Docstring. - ;; MAYBE: Use `noflet'. - (declare (indent defun) (debug (listp body))) - `(cl-letf ,(cl-loop for (fn target) in fns - collect `((symbol-function ',fn) - (symbol-function ,target))) - ,@body)) - ;;;; Functions (cl-defun org-ql-query (buffers-or-files query &key action narrow sort) From 42138e2673586301da5854b985648dcef506b1c8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 13:49:41 -0500 Subject: [PATCH 184/970] Docs: Update docstrings To comply with checkdoc. --- org-ql-agenda.el | 4 +++- org-ql.el | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index c8d6074..f073f61 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -294,7 +294,7 @@ dates in the past, and negative for dates in the future." (defun org-ql-agenda--format-element (element) ;; This essentially needs to do what `org-agenda-format-item' does, ;; which is a lot. We are a long way from that, but it's a start. - "Return ELEMENT as a string with its text-properties set according to its property list. + "Return ELEMENT as a string with text-properties set by its property list. Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." (let* ((properties (cadr element)) ;; Remove the :parent property, which so bloats the size of @@ -364,6 +364,7 @@ Its property list should be the second item in the list, as returned by `org-ele 'org-habit-p habit-property)))) (defun org-ql-agenda--add-faces (element) + "Return ELEMENT with deadline and scheduled faces added." (->> element (org-ql-agenda--add-scheduled-face) (org-ql-agenda--add-deadline-face))) @@ -465,6 +466,7 @@ property." element)) (defun org-ql-agenda--add-todo-face (keyword) + "Return KEYWORD with TODO face added." (when-let ((face (org-get-todo-face keyword))) (org-add-props keyword nil 'face face))) diff --git a/org-ql.el b/org-ql.el index 93edb60..7518ee0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -355,7 +355,7 @@ from within ELEMENT's buffer." element)) (defun org-ql--sanity-check-form (form) - "Signal an error if any of the forms in BODY do not have their preconditions met. + "Signal error if any forms in FORM do not have preconditions met. Or, when possible, fix the problem." (cl-flet ((check (symbol) (cl-case symbol @@ -535,7 +535,7 @@ comparator, PRIORITY should be a priority string." (org-ql--defpredicate property (property &optional value) "Return non-nil if current entry has PROPERTY (a string), and optionally VALUE (a string)." (pcase property - ('nil (user-error "Property matcher requires a PROPERTY argument.")) + ('nil (user-error "Property matcher requires a PROPERTY argument")) (_ (pcase value ('nil ;; Check that PROPERTY exists @@ -860,7 +860,7 @@ A and B are Org headline elements. TYPE should be a symbol like (org-element-property type b))) (defun org-ql--date< (a b) - "Return non-nil if A's deadline or scheduled element property is earlier than B's. + "Return non-nil if A's deadline or scheduled property is earlier than B's. Deadline is considered before scheduled." (cl-macrolet ((ts (item) `(or (org-element-property :deadline ,item) From 9648dd12f930569dd61661822d95869bc3a6ec73 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:46:19 -0500 Subject: [PATCH 185/970] Tidy: Headers, commentaries, etc. --- org-ql-agenda.el | 31 +++++++++++++------------------ org-ql.el | 22 +++++++++++++++++++--- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index f073f61..1e8a229 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -2,32 +2,27 @@ ;; Author: Adam Porter ;; Url: http://github.com/alphapapa/org-ql -;; Version: 0.1-pre -;; Package-Requires: ((emacs "25.1") (dash "2.13") (org "9.0")) -;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: -;; This library displays buffers similar to Org Agenda buffers, based +;; This library is part of the package `org-ql'; it's not a standalone +;; library. It displays buffers similar to Org Agenda buffers, based ;; on `org-ql' queries. -;;;; Principles +;;; License: -;;;;; Try to imitate traditional Org agenda code's results and methods +;; 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. -;; The traditional agenda code is complicated, but well-optimized. We should imitate it where -;; possible. We should also attempt to return the same results as the traditional agenda code -;; (ultimately, that is; but whether we reach that level of complexity depends on, e.g. performance -;; achieved, whether it looks like a feasible alternative, etc). At the least, we should return -;; results in the same format, so they can be used by other code that uses agenda output -;; (e.g. org-agenda-finalize-entries, org-agenda-finalize, org-super-agenda, etc). Of course, this -;; goal does not necessarily apply to the "query language"-like features, and ideally the -;; agenda-like features should build upon those. +;; 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. -;;;;; Preserve the call to =org-agenda-finalize-entries= - -;; We want to preserve the final call to org-agenda-finalize-entries to preserve compatibility -;; with other packages and functions. +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . ;;; Code: diff --git a/org-ql.el b/org-ql.el index 7518ee0..14445e9 100644 --- a/org-ql.el +++ b/org-ql.el @@ -9,9 +9,25 @@ ;;; Commentary: ;; `org-ql' is a lispy query language for Org files. It allows you to -;; find Org entries matching certain criteria and perform actions on -;; them, such as collecting their parsed representation with -;; `org-element' (the default action). +;; find Org entries matching certain criteria and return a list of +;; them or perform actions on them. Commands are also provided which +;; display a buffer with matching results, similar to an Org Agenda +;; buffer. + +;;; 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: From c6250d1ee25f0bac970eddc4ace5ed520a0e8778 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:50:06 -0500 Subject: [PATCH 186/970] Tidy: Docstring --- org-ql.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 14445e9..d8e3ed6 100644 --- a/org-ql.el +++ b/org-ql.el @@ -67,7 +67,13 @@ This list should not contain any duplicates.") ;;;; Macros (cl-defmacro org-ql--defpredicate (name args docstring &rest body) - "FIXME: docstring" + "Define an `org-ql' selector predicate named `org-ql--predicate-NAME'. +ARGS is a `cl-defun'-style argument list. DOCSTRING is the +function's 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)) (indent defun)) (let ((fn-name (intern (concat "org-ql--predicate-" (symbol-name name)))) From 3a2eaceca89e493306592fc7dff0887df0335210 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:51:59 -0500 Subject: [PATCH 187/970] Tidy: Move defvar --- org-ql.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/org-ql.el b/org-ql.el index d8e3ed6..d44e402 100644 --- a/org-ql.el +++ b/org-ql.el @@ -51,6 +51,11 @@ (defvar org-ql--today nil) +(defvar org-ql-use-preamble t + ;; MAYBE: Naming things is hard. There must be a better term than "preamble." + "Use query preambles to speed up searches. +May be disabled for debugging, benchmarks, etc.") + (defvar org-ql-cache (make-hash-table :weakness 'key) ;; IIUC, setting weakness to `key' means that, when a buffer is closed, ;; its entries will be removed from this table at the next GC. @@ -247,11 +252,6 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) (sxhash-equal (prin1-to-string args)))) -(defvar org-ql-use-preamble t - ;; FIXME: Move or delete this defvar. - "Use query preambles to speed up searches. -May be disabled for debugging, benchmarks, etc.") - (defun org-ql--query-preamble (query) "Return (QUERY PREAMBLE) for QUERY. When QUERY has a clause with a corresponding preamble, and it's From cf75e2fb1dfccfbea8a130013514e7c0e91c3c3b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:52:41 -0500 Subject: [PATCH 188/970] Tidy: Move hash-table-test def --- org-ql.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index d44e402..97315e5 100644 --- a/org-ql.el +++ b/org-ql.el @@ -129,6 +129,9 @@ buffer. In this case, ACTION should return an Org element." ;;;; Functions +(define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) + (sxhash-equal (prin1-to-string args)))) + (cl-defun org-ql-query (buffers-or-files query &key action narrow sort) "Return items matching QUERY in BUFFERS-OR-FILES. @@ -249,9 +252,6 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (org-ql--sort-by items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) -(define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) - (sxhash-equal (prin1-to-string args)))) - (defun org-ql--query-preamble (query) "Return (QUERY PREAMBLE) for QUERY. When QUERY has a clause with a corresponding preamble, and it's From b2e35997c769a6ae034fedf9cbf9c3c3659f76f6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:54:31 -0500 Subject: [PATCH 189/970] Tidy: Rename macro to --defpred --- org-ql.el | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/org-ql.el b/org-ql.el index 97315e5..8d568c0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -71,7 +71,7 @@ This list should not contain any duplicates.") ;;;; Macros -(cl-defmacro org-ql--defpredicate (name args docstring &rest body) +(cl-defmacro org-ql--defpred (name args docstring &rest body) "Define an `org-ql' selector predicate named `org-ql--predicate-NAME'. ARGS is a `cl-defun'-style argument list. DOCSTRING is the function's docstring. BODY is the body of the predicate. @@ -412,7 +412,7 @@ empty time values to 23:59:59; otherwise, to 00:00:00." ;;;;; Predicates -(org-ql--defpredicate 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. "Return non-nil if current entry was clocked in given period. @@ -451,14 +451,14 @@ ignored." (from (test-timestamps (<= from end))) (to (test-timestamps (<= beg to)))))))) -(org-ql--defpredicate 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))))) -(org-ql--defpredicate todo (&rest keywords) +(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))) @@ -468,12 +468,12 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin (symbol (member state (symbol-value keywords))) (otherwise (user-error "Invalid todo keywords: %s" keywords))))) -(org-ql--defpredicate 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))) -(org-ql--defpredicate tags (&rest tags) +(org-ql--defpred tags (&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. @@ -482,7 +482,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin (null t) (otherwise (seq-intersection tags tags-at))))) -(org-ql--defpredicate level (level-or-comparator &optional level) +(org-ql--defpred level (level-or-comparator &optional level) "Return non-nil if current heading's outline level matches LEVEL with COMPARATOR. If LEVEL is nil, LEVEL-OR-COMPARATOR should be an integer level, @@ -498,7 +498,7 @@ function (like `<=')." ;; Check with comparator (_ (funcall level-or-comparator outline-level level))))) -(org-ql--defpredicate priority (&optional comparator-or-priority priority) +(org-ql--defpred 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 (`=' @@ -535,11 +535,11 @@ comparator, PRIORITY should be a priority string." (org-get-priority (match-string 0))))))) (funcall comparator priority item-priority)))) -(org-ql--defpredicate habit () +(org-ql--defpred habit () "Return non-nil if entry is a habit." (org-is-habit-p)) -(org-ql--defpredicate regexp (&rest regexps) +(org-ql--defpred regexp (&rest regexps) "Return non-nil if current entry matches one of REGEXPS (regexp strings)." (let ((end (or (save-excursion (outline-next-heading)) @@ -550,11 +550,11 @@ comparator, PRIORITY should be a priority string." thereis (save-excursion (re-search-forward regexp end t)))))) -(org-ql--defpredicate heading (regexp) +(org-ql--defpred heading (regexp) "Return non-nil if current entry's heading matches REGEXP (a regexp string)." (string-match regexp (org-get-heading 'no-tags 'no-todo))) -(org-ql--defpredicate 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)." (pcase property ('nil (user-error "Property matcher requires a PROPERTY argument")) @@ -573,7 +573,7 @@ comparator, PRIORITY should be a priority string." ;; and language-independent than using from/to. Alternatively, add :before/:after, but I ;; think the comparators are better. Also consider using a macro to DRY these out. -(org-ql--defpredicate ts (&key from to _on) +(org-ql--defpred 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. @@ -613,7 +613,7 @@ FROM, TO, and ON should be strings parseable by (from (test-timestamps (<= from end))) (to (test-timestamps (<= beg to)))))))) -(org-ql--defpredicate ts-active (&key from to _on) +(org-ql--defpred ts-active (&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 an active timestamp in given period. @@ -656,7 +656,7 @@ FROM, TO, and ON should be strings parseable by (from (test-timestamps (<= from end))) (to (test-timestamps (<= beg to)))))))) -(org-ql--defpredicate ts-inactive (&key from to _on) +(org-ql--defpred ts-inactive (&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 an inactive timestamp in given period. @@ -744,7 +744,7 @@ like one returned by `date-to-day'." (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" comparator target-date))))) -(org-ql--defpredicate planning (&optional comparator target-date) +(org-ql--defpred planning (&optional comparator target-date) "Return non-nil if entry's planning date (deadline or scheduled) compares with TARGET-DATE using COMPARATOR. TARGET-DATE should be a string parseable by `date-to-day'. COMPARATOR should be a function (like `<=')." @@ -752,7 +752,7 @@ COMPARATOR should be a function (like `<=')." ;; FIXME: I think :date selects either :deadline, :scheduled, or :closed, but I'm not sure. (org-ql--date-type-p :date comparator target-date)) -(org-ql--defpredicate deadline (&optional comparator target-date) +(org-ql--defpred deadline (&optional comparator target-date) "Return non-nil if entry's deadline compares with TARGET-DATE using COMPARATOR. TARGET-DATE should be a string parseable by `date-to-day'; or if omitted, it is determined automatically using @@ -768,21 +768,21 @@ function (like `<=')." ;; selectors, which would also be unintuitive. (org-ql--date-type-p :deadline comparator target-date)) -(org-ql--defpredicate scheduled (&optional comparator target-date) +(org-ql--defpred scheduled (&optional comparator target-date) "Return non-nil if entry's scheduled date compares with TARGET-DATE using COMPARATOR. TARGET-DATE should be a string parseable by `date-to-day'. COMPARATOR should be a function (like `<=')." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :scheduled comparator target-date)) -(org-ql--defpredicate closed (&optional comparator target-date) +(org-ql--defpred closed (&optional comparator target-date) "Return non-nil if entry's closed date compares with TARGET-DATE using COMPARATOR. TARGET-DATE should be a string parseable by `date-to-day'. COMPARATOR should be a function (like `<=')." ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. (org-ql--date-type-p :closed comparator target-date)) -(org-ql--defpredicate date (&optional comparator target-date (type 'active)) +(org-ql--defpred date (&optional comparator target-date (type 'active)) "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. Checks all Org-formatted timestamp strings in entry. TYPE may be `active', `inactive', or `all', to control whether active, From 66f36be2caf42fe355b87cbadab9055f7310b451 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 18:56:51 -0500 Subject: [PATCH 190/970] Tidy: Remove unused function --- org-ql.el | 3 --- 1 file changed, 3 deletions(-) diff --git a/org-ql.el b/org-ql.el index 8d568c0..af73865 100644 --- a/org-ql.el +++ b/org-ql.el @@ -855,9 +855,6 @@ PREDICATES is a list of one or more sorting methods, including: ;; NOTE: 'todo is handled below ;; FIXME: Add more? (_ (user-error "Invalid sorting predicate: %s" symbol)))) - (todo-keyword-pos (keyword) - ;; MAYBE: Would it be faster to precompute these and do an alist lookup? - (cl-position keyword org-todo-keywords-1 :test #'string=)) (sort-by-todo-keyword (items) (let* ((grouped-items (--group-by (when-let (keyword (org-element-property :todo-keyword it)) (substring-no-properties keyword)) From bc4bdc158702574eba8378eccd5489f3ba9f1d08 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 19:01:26 -0500 Subject: [PATCH 191/970] Comment: Add MAYBE --- org-ql-agenda.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 1e8a229..48c8e4e 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -275,6 +275,7 @@ default buffer." (current-buffer))) (defun org-ql-agenda--format-relative-date (difference) + ;; MAYBE: Make this a `defsubst'. "Return relative date string for DIFFERENCE. DIFFERENCE should be an integer number of days, positive for dates in the past, and negative for dates in the future." From 0f963fc81192254bc9dccf80617d3ba95f606ba9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 19:01:33 -0500 Subject: [PATCH 192/970] Tidy: Parens --- org-ql-agenda.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 48c8e4e..921d121 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -314,8 +314,7 @@ Its property list should be the second item in the list, as returned by `org-ele ;; (which would also make it easier to do it independently of faces, etc). (title (--> (org-ql-agenda--add-faces element) (org-element-property :raw-value it) - (org-link-display-format it) - )) + (org-link-display-format it))) (todo-keyword (-some--> (org-element-property :todo-keyword element) (org-ql-agenda--add-todo-face it))) ;; FIXME: Figure out whether I should use `org-agenda-use-tag-inheritance' or `org-use-tag-inheritance', etc. From 9846be03b9c9bbdc8665cb8958b8b1b561719974 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 19:07:44 -0500 Subject: [PATCH 193/970] Tidy: Docstring --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index af73865..6617e2b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -108,7 +108,7 @@ one or more sorting methods, including: `date', `deadline', If NARROW is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). -If MARKERS is non-nil, `org-agenda-ng--add-markers' is used to +If MARKERS is non-nil, `org-ql--add-markers' is used to add markers to each item, pointing to the item in its source buffer. In this case, ACTION should return an Org element." (declare (indent defun)) From 18def9313acdc8e55278b38b8cc84d086fe8b6ce Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 19:07:55 -0500 Subject: [PATCH 194/970] Change: (org-ql-agenda--agenda) Avoid eval --- org-ql-agenda.el | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 921d121..0aced86 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -206,13 +206,14 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (declare (indent defun)) (when (and super-groups (not org-super-agenda-mode)) (user-error "`org-super-agenda-mode' must be activated to use grouping")) - ;; I think it's reasonable to use `eval' here. (let* ((org-super-agenda-groups super-groups) - (entries (--> (eval `(org-ql ',buffers-files - ,query - :sort ,sort - :markers t - :narrow ,narrow)) + (entries (--> (org-ql-query buffers-files + query + :sort sort + :narrow narrow + :action (lambda () + (->> (org-element-headline-parser (line-end-position)) + org-ql--add-markers))) (mapcar #'org-ql-agenda--format-element it) (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) (t it)) From 75d8fd534fdfe6020a98ab1a13a93abe884d25a4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 16 Jul 2019 19:17:56 -0500 Subject: [PATCH 195/970] Tidy: Buffer name --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 0aced86..faf6813 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -50,7 +50,7 @@ ;;;; Variables -(defvar org-ql-agenda-buffer-name "*Org Agenda NG*" +(defvar org-ql-agenda-buffer-name "*Org-QL-Agenda*" "Name of default `org-ql-agenda' buffer.") ;; For refreshing results buffers. From 8a8f78408c504c99094ac9b1f1dfbb22435c4824 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 09:20:53 -0500 Subject: [PATCH 196/970] Fix: Declare org-super-agenda as ext --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index faf6813..bba97aa 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -43,7 +43,7 @@ (defvar org-super-agenda-auto-selector-keywords) (defvar org-super-agenda-groups) (defvar org-super-agenda-mode) -(declare-function org-super-agenda--group-items "org-super-agenda") +(declare-function org-super-agenda--group-items "ext:org-super-agenda") (when (version< org-version "9.2") (defalias 'org-get-tags 'org-get-tags-at)) From 3e9f3276c0bdbab6e164410116229f05b6765347 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 09:22:01 -0500 Subject: [PATCH 197/970] Fix: Sharp-quote alias targets --- org-ql-agenda.el | 2 +- org-ql.el | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index bba97aa..89c9364 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -46,7 +46,7 @@ (declare-function org-super-agenda--group-items "ext:org-super-agenda") (when (version< org-version "9.2") - (defalias 'org-get-tags 'org-get-tags-at)) + (defalias 'org-get-tags #'org-get-tags-at)) ;;;; Variables diff --git a/org-ql.el b/org-ql.el index 6617e2b..a01a0e8 100644 --- a/org-ql.el +++ b/org-ql.el @@ -44,8 +44,8 @@ ;;;; Compatibility (when (version< org-version "9.2") - (defalias 'org-get-tags 'org-get-tags-at) - (defalias 'org-timestamp-to-time 'org-timestamp--to-internal-time)) + (defalias 'org-get-tags #'org-get-tags-at) + (defalias 'org-timestamp-to-time #'org-timestamp--to-internal-time)) ;;;; Variables From 2a40b180076b5d8959904d6a354a8acc3889abe8 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 09:22:08 -0500 Subject: [PATCH 198/970] Fix: (org-ql-search) Space ending prompt string --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 89c9364..8ff3a9f 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -154,7 +154,7 @@ searching. Interactively, with prefix, leave narrowed. SORT: One or a list of `org-ql' sorting functions, like `date' or `priority'." (declare (indent defun)) - (interactive (list (pcase-exhaustive (completing-read "Buffers/Files:" + (interactive (list (pcase-exhaustive (completing-read "Buffers/Files: " (list 'buffer 'agenda 'all)) ("agenda" (org-agenda-files)) ("all" (--select (equal (buffer-local-value 'major-mode it) 'org-mode) From f39e752db3a3172049e33f9e37297e697cbcd8b5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 09:23:41 -0500 Subject: [PATCH 199/970] Tidy: http->https --- org-ql-agenda.el | 4 ++-- org-ql.el | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 8ff3a9f..d0e4a67 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -1,7 +1,7 @@ ;;; org-ql-agenda.el --- Agenda-like view based on org-ql -*- lexical-binding: t; -*- ;; Author: Adam Porter -;; Url: http://github.com/alphapapa/org-ql +;; Url: https://github.com/alphapapa/org-ql ;;; Commentary: @@ -22,7 +22,7 @@ ;; 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 . +;; along with this program. If not, see . ;;; Code: diff --git a/org-ql.el b/org-ql.el index a01a0e8..acc5935 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1,7 +1,7 @@ ;;; org-ql.el --- Query language for Org buffers -*- lexical-binding: t; -*- ;; Author: Adam Porter -;; Url: http://github.com/alphapapa/org-ql +;; Url: https://github.com/alphapapa/org-ql ;; Version: 0.2-pre ;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.0") (s "1.12.0")) ;; Keywords: hypermedia, outlines, Org, agenda @@ -27,7 +27,7 @@ ;; 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 . +;; along with this program. If not, see . ;;; Code: From 25ed67a37d617670dbdd76e9423ef2f2f987692b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 11:53:51 -0500 Subject: [PATCH 200/970] Change: (--date-type-p) More detailed error for unknown date types --- org-ql.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index acc5935..04c81ca 100644 --- a/org-ql.el +++ b/org-ql.el @@ -740,7 +740,8 @@ like one returned by `date-to-day'." (org-time-string-to-absolute (org-element-timestamp-interpreter date-element 'ignore)) target-day-number)) - (_ (error "Unknown date-element type: %s" (org-element-property :type date-element)))))) + (_ (error "Unknown date-element type \"%s\" in buffer %s at position %s" + (org-element-property :type date-element) (current-buffer) (point)))))) (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" comparator target-date))))) From 25f964dfcb723aa573f30217b079fba42fcf9d00 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 17 Jul 2019 12:04:28 -0500 Subject: [PATCH 201/970] Fix: (--date-type-p) Handle ranges I meant to do this in c5599a6, but I omitted the range type symbol when I rewrote the selector and functions. This should work now. Thanks to @codygman, @swflint, and @vikasrawal. --- README.org | 3 +++ org-ql.el | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 698197d..6997688 100644 --- a/README.org +++ b/README.org @@ -236,6 +236,9 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to *Changed* + ~(regexp)~ selector accepts multiple regexps to test. +*Fixed* ++ Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) + *Compatibility* + Fixes for compatibility with Org 9.2. (Thanks to [[https://github.com/ataias][Ataias Pereira Reis]] and [[https://github.com/dakra][Daniel Kraus]].) diff --git a/org-ql.el b/org-ql.el index 04c81ca..0360a28 100644 --- a/org-ql.el +++ b/org-ql.el @@ -735,7 +735,7 @@ like one returned by `date-to-day'." (string (date-to-day (concat target-date " 00:00"))) (integer target-date)))) (pcase (org-element-property :type date-element) - ((or 'active 'inactive) + ((or 'active 'inactive 'active-range 'inactive-range) (funcall comparator (org-time-string-to-absolute (org-element-timestamp-interpreter date-element 'ignore)) From c31f8736255583588624deec2a502d1285e1a70e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 18 Jul 2019 01:20:25 -0500 Subject: [PATCH 202/970] Fix: Define own get-tags function for compatibility In Org <9.2, both org-get-tags and org-get-tags-at are functions, and we must not clobber org-get-tags. In Org 9.2+, org-get-tags replaces org-get-tags-at, but org-get-tags-at remains defined as an obsolete alias. Thanks to Chris Rayner (@riscy). --- org-ql.el | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/org-ql.el b/org-ql.el index 0360a28..78abc4e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -43,9 +43,13 @@ ;;;; Compatibility -(when (version< org-version "9.2") - (defalias 'org-get-tags #'org-get-tags-at) - (defalias 'org-timestamp-to-time #'org-timestamp--to-internal-time)) +(if (version< org-version "9.2") + (progn + (defalias 'org-timestamp-to-time #'org-timestamp--to-internal-time) + (defun org-ql--get-tags (&optional pos local) + (org-get-tags-at pos local))) + (defun org-ql--get-tags (&optional pos local) + (org-get-tags pos local))) ;;;; Variables @@ -477,7 +481,7 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin "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. - (when-let ((tags-at (org-get-tags (point) (not org-use-tag-inheritance)))) + (when-let ((tags-at (org-ql--get-tags (point) (not org-use-tag-inheritance)))) (cl-typecase tags (null t) (otherwise (seq-intersection tags tags-at))))) From f6d2d1e5374c9b8a8f8565f3222c42371db1b95d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 10:16:16 -0500 Subject: [PATCH 203/970] Fix: Use org-timestamp-to-time everywhere These changes should have been in adcb96c. Thanks to Chris Rayner (@riscy) for noticing this omission. --- org-ql.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/org-ql.el b/org-ql.el index 78abc4e..a24fa2f 100644 --- a/org-ql.el +++ b/org-ql.el @@ -443,8 +443,8 @@ ignored." `(cl-loop for next-ts = (next-timestamp) while next-ts ;; Using `setf' instead of `for beg =` here prevents "unused lexical variable" warnings. - do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) - end (float-time (org-timestamp--to-internal-time next-ts 'end))) + do (setf beg (float-time (org-timestamp-to-time next-ts)) + end (float-time (org-timestamp-to-time next-ts 'end))) thereis ,pred-form))) (save-excursion (let ((end-pos (org-entry-end-position)) @@ -605,8 +605,8 @@ FROM, TO, and ON should be strings parseable by (test-timestamps (pred-form) `(cl-loop for next-ts = (next-timestamp) while next-ts - do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) - end (float-time (org-timestamp--to-internal-time next-ts 'end))) + do (setf beg (float-time (org-timestamp-to-time next-ts)) + end (float-time (org-timestamp-to-time next-ts 'end))) thereis ,pred-form))) (save-excursion (let ((end-pos (org-entry-end-position)) @@ -648,8 +648,8 @@ FROM, TO, and ON should be strings parseable by `(cl-loop for next-ts = (next-timestamp) while next-ts when (string-prefix-p "<" next-ts) - do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) - end (float-time (org-timestamp--to-internal-time next-ts 'end))) + do (setf beg (float-time (org-timestamp-to-time next-ts)) + end (float-time (org-timestamp-to-time next-ts 'end))) thereis ,pred-form))) (save-excursion (let ((end-pos (org-entry-end-position)) @@ -691,8 +691,8 @@ FROM, TO, and ON should be strings parseable by `(cl-loop for next-ts = (next-timestamp) while next-ts when (string-prefix-p "[" next-ts) - do (setf beg (float-time (org-timestamp--to-internal-time next-ts)) - end (float-time (org-timestamp--to-internal-time next-ts 'end))) + do (setf beg (float-time (org-timestamp-to-time next-ts)) + end (float-time (org-timestamp-to-time next-ts 'end))) thereis ,pred-form))) (save-excursion (let ((end-pos (org-entry-end-position)) From b1b04b3f19517cff42267a90147dcf48d5c1d95b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 17:42:08 -0500 Subject: [PATCH 204/970] Docs: Add badges --- README.org | 6 ++++++ images/dont-tread-on-emacs-150.png | Bin 0 -> 5660 bytes 2 files changed, 6 insertions(+) create mode 100644 images/dont-tread-on-emacs-150.png diff --git a/README.org b/README.org index 6997688..91ca0dc 100644 --- a/README.org +++ b/README.org @@ -1,5 +1,11 @@ #+TITLE: org-ql +#+BEGIN_HTML + +#+END_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]] + ~org-ql~ is a lispy query language for Org files. It allows you to find Org entries matching certain criteria and return a list of them or perform actions on them. Commands are also provided which display a buffer with matching results, similar to an Org Agenda buffer. * Contents diff --git a/images/dont-tread-on-emacs-150.png b/images/dont-tread-on-emacs-150.png new file mode 100644 index 0000000000000000000000000000000000000000..71f37362a5289714efa07aed1e7520198e8f8b87 GIT binary patch literal 5660 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 T9~Ln%Ffe$!`njxgN@xNAk>vYn literal 0 HcmV?d00001 From 0fdfa65bef7d5f05137ccaa7d8e16b81e5c97ddf Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 18:17:17 -0500 Subject: [PATCH 205/970] Change: (--query-preamble) Add (level) preamble --- notes.org | 26 ++++++++++++++++++++++++++ org-ql.el | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/notes.org b/notes.org index 66af1a3..4a390fc 100644 --- a/notes.org +++ b/notes.org @@ -410,6 +410,32 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled * Profiling +** Preambles + +#+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))) + ("no preamble" ((org-ql-use-preamble nil)))) + :forms ((,(prin1-to-string query) (org-ql-query ,file + ',query + :action (lambda () (org-get-heading t t))))))) +#+END_SRC + +*** =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 | + ** 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. diff --git a/org-ql.el b/org-ql.el index a24fa2f..6da5c9e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -282,6 +282,10 @@ replace the clause with a preamble." (setq org-ql-preamble regexp) ;; Return nil nil)) + (`(level ,num) + (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ")))) + (setq org-ql-preamble regexp) + nil)) (`(and . ,rest) (let ((clauses (mapcar #'rec rest))) `(and ,@(-non-nil clauses)))) From a56d173eb52ada86089d173e98bcfed636849a9c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 22:57:58 -0500 Subject: [PATCH 206/970] Change: (--query-preamble) Use pcase for clarity --- org-ql.el | 76 +++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/org-ql.el b/org-ql.el index 6da5c9e..f48377e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -261,44 +261,44 @@ a list of defined `org-ql' sorting methods: `date', `deadline', 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." - (if org-ql-use-preamble - (let (org-ql-preamble) - (cl-labels ((rec (element) - (or (when org-ql-preamble - ;; Only one preamble is allowed - element) - (pcase element - (`(or _) element) - (`(regexp . ,regexps) - (let* ((regexp (rx-to-string `(or ,@regexps)))) - (setq org-ql-preamble regexp) - ;; Return nil - nil)) - (`(todo . ,(and todo-keywords (guard todo-keywords))) - (let* ((regexps (--map (list 'regexp - (format org-heading-keyword-regexp-format it)) - todo-keywords)) - (regexp (rx-to-string `(or ,@regexps)))) - (setq org-ql-preamble regexp) - ;; Return nil - nil)) - (`(level ,num) - (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ")))) - (setq org-ql-preamble regexp) - nil)) - (`(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 org-ql-preamble))) - (list query nil))) + (pcase org-ql-use-preamble + ('nil (list query nil)) + (_ (let (org-ql-preamble) + (cl-labels ((rec (element) + (or (when org-ql-preamble + ;; Only one preamble is allowed + element) + (pcase element + (`(or _) element) + (`(regexp . ,regexps) + (let* ((regexp (rx-to-string `(or ,@regexps)))) + (setq org-ql-preamble regexp) + ;; Return nil + nil)) + (`(todo . ,(and todo-keywords (guard todo-keywords))) + (let* ((regexps (--map (list 'regexp + (format org-heading-keyword-regexp-format it)) + todo-keywords)) + (regexp (rx-to-string `(or ,@regexps)))) + (setq org-ql-preamble regexp) + ;; Return nil + nil)) + (`(level ,num) + (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ")))) + (setq org-ql-preamble regexp) + nil)) + (`(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 org-ql-preamble)))))) (defun org-ql--select-cached (&rest args) "Return results for ARGS and current buffer using cache." From 2b0730d53b96b3fa82471df49165512a4761db0a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 23:11:07 -0500 Subject: [PATCH 207/970] Comment: Add FIXME --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index f48377e..8c956e0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -222,6 +222,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (<= #'<=) (>= #'>=)) ,query)))))) + ;; FIXME: Don't try to byte-compile already-compiled functions. (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) From ac402e33c74504d3e380cf89df4a8f31ddb066d5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 23:11:17 -0500 Subject: [PATCH 208/970] Add/Change: (--query-predicate) Move code to new function --- org-ql.el | 120 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 62 insertions(+), 58 deletions(-) diff --git a/org-ql.el b/org-ql.el index 8c956e0..2e84580 100644 --- a/org-ql.el +++ b/org-ql.el @@ -164,64 +164,7 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (_ ; Buffer or string (list buffers-or-files)))) ((query preamble-re) (org-ql--query-preamble query)) - (predicate (byte-compile `(lambda () - ;; This is either really elegant or really ugly. Well, also - ;; possibly somewhere in-between. At the least, we should do - ;; this in a more flexible, abstracted way, but this will do - ;; for now. Most importantly, it works! - (let (from to on) - ;; TODO: DRY these macrolets. - (cl-macrolet ((clocked (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' - ;; function, not another `clocked'. - `(org-ql--predicate-clocked :from ,from :to ,to)) - (ts (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts :from ,from :to ,to)) - (ts-active (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-active :from ,from :to ,to)) - (ts-inactive (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-inactive :from ,from :to ,to))) - (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda - (= #'=) - (< #'<) - (> #'>) - (<= #'<=) - (>= #'>=)) - ,query)))))) + (predicate (org-ql--query-predicate query)) ;; FIXME: Don't try to byte-compile already-compiled functions. (action (byte-compile action)) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. @@ -257,6 +200,67 @@ a list of defined `org-ql' sorting methods: `date', `deadline', (org-ql--sort-by items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) +(defun org-ql--query-predicate (query) + "Return predicate function for QUERY." + (byte-compile `(lambda () + ;; This is either really elegant or really ugly. Well, also + ;; possibly somewhere in-between. At the least, we should do + ;; this in a more flexible, abstracted way, but this will do + ;; for now. Most importantly, it works! + (let (from to on) + ;; TODO: DRY these macrolets. + (cl-macrolet ((clocked (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' + ;; function, not another `clocked'. + `(org-ql--predicate-clocked :from ,from :to ,to)) + (ts (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts :from ,from :to ,to)) + (ts-active (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-active :from ,from :to ,to)) + (ts-inactive (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (org-ql--parse-time-string from))) + (when to + (setq to (org-ql--parse-time-string to 'end))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' + ;; function, not another `ts'. + `(org-ql--predicate-ts-inactive :from ,from :to ,to))) + (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda + (= #'=) + (< #'<) + (> #'>) + (<= #'<=) + (>= #'>=)) + ,query)))))) + (defun org-ql--query-preamble (query) "Return (QUERY PREAMBLE) for QUERY. When QUERY has a clause with a corresponding preamble, and it's From 3133c4f33bca22d4f5f2e07cabe8207c1f186554 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 20 Jul 2019 23:18:39 -0500 Subject: [PATCH 209/970] Change: (org-ql-query) Simplify --- org-ql.el | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/org-ql.el b/org-ql.el index 2e84580..debed89 100644 --- a/org-ql.el +++ b/org-ql.el @@ -158,11 +158,18 @@ 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', and `priority'." (declare (indent defun)) - (-let* ((sources (pcase buffers-or-files - (`nil (list (current-buffer))) - ((pred listp) buffers-or-files) - (_ ; Buffer or string - (list buffers-or-files)))) + (-let* ((buffers (->> (cl-typecase buffers-or-files + (null (list (current-buffer))) + (list buffers-or-files) + (otherwise (list buffers-or-files))) + (--map (cl-etypecase it + (buffer it) + (string (or (find-buffer-visiting it) + (when (file-readable-p it) + ;; It feels unintuitive that `find-file-noselect' returns + ;; a buffer if the filename doesn't exist. + (find-file-noselect it)) + (user-error "Can't open file: %s" it))))))) ((query preamble-re) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) ;; FIXME: Don't try to byte-compile already-compiled functions. @@ -171,23 +178,12 @@ a list of defined `org-ql' sorting methods: `date', `deadline', ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) (org-ql--today (org-today)) - (items (->> sources - ;; List buffers - (--map (cl-etypecase it - (buffer it) - (string (or (find-buffer-visiting it) - (when (file-readable-p it) - ;; It feels unintuitive that `find-file-noselect' returns - ;; a buffer if the filename doesn't exist. - (find-file-noselect it)) - (user-error "Can't open file: %s" it))))) - ;; Filter buffers (i.e. select items) + (items (->> buffers (--map (with-current-buffer it (unless (derived-mode-p 'org-mode) (user-error "Not an Org buffer: %s" (buffer-name))) (org-ql--select-cached :query query :preamble-re preamble-re :predicate predicate :action action :narrow narrow))) - ;; Flatten items (-flatten-n 1)))) ;; Sort items (pcase sort From 88ba3d3933ede18f5e48e4463e4d58bf9d981b11 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 21 Jul 2019 17:21:17 -0500 Subject: [PATCH 210/970] Docs: (org-ql) Improve docstring --- README.org | 2 ++ org-ql.el | 3 +++ 2 files changed, 5 insertions(+) diff --git a/README.org b/README.org index 91ca0dc..7d1cdd0 100644 --- a/README.org +++ b/README.org @@ -218,6 +218,8 @@ If ~NARROW~ is non-nil, buffers are not widened. Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. +Unlike the corresponding function ~org-ql-query~, arguments to this macro should not be quoted. + ~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). ~QUERY~ is an ~org-ql~ query sexp, unquoted. diff --git a/org-ql.el b/org-ql.el index debed89..39f9221 100644 --- a/org-ql.el +++ b/org-ql.el @@ -95,6 +95,9 @@ match." (action '(org-element-headline-parser (line-end-position)))) "Find entries in BUFFERS-OR-FILES that match QUERY, and return the results of running ACTION-FN on each matching entry. +Unlike the corresponding function `org-ql-query', arguments to +this macro should not be quoted. + BUFFERS-OR-FILES is a form which should evaluate to one (or a list of) file(s) or buffer(s). From 797798bd084ab62490b0ef38582bd57ee1f59c00 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 21 Jul 2019 17:21:48 -0500 Subject: [PATCH 211/970] Change: (org-ql-query) Accept comparator function to :sort --- README.org | 3 ++- org-ql.el | 16 +++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/README.org b/README.org index 7d1cdd0..34dde96 100644 --- a/README.org +++ b/README.org @@ -210,7 +210,7 @@ Return items matching ~QUERY~ in ~BUFFERS-OR-FILES~. If ~NARROW~ is non-nil, buffers are not widened. -~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~, and ~priority~. +~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~, or ~priority~); or a user-defined comparator function that accepts two items as arguments and returns nil or non-nil. **** Macro: ~org-ql~ @@ -243,6 +243,7 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to *Changed* + ~(regexp)~ selector accepts multiple regexps to test. ++ The ~:sort~ argument to ~org-ql~, ~org-ql-query~, etc. now also accepts a comparator function by which to sort items. *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) diff --git a/org-ql.el b/org-ql.el index 39f9221..363b8de 100644 --- a/org-ql.el +++ b/org-ql.el @@ -108,9 +108,11 @@ with point at the beginning of its heading. It is passed to `org-ql-query' as a lambda. By default, `org-element-headline-parser' is called to return an Org element. -SORT is a user defined sorting function, or an unquoted list of -one or more sorting methods, including: `date', `deadline', -`scheduled', `todo', and `priority'. +SORT is either nil, in which case items are not sorted; or one or +a list of predefined `org-ql' sorting methods (`date', `deadline', +`scheduled', `todo', or `priority'; or a user-defined comparator +function that accepts two items as arguments and returns nil or +non-nil. If NARROW is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). @@ -158,8 +160,10 @@ compatible with Org Agenda code. If NARROW is non-nil, buffers are not widened. 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', and `priority'." +a list of defined `org-ql' sorting methods (`date', `deadline', +`scheduled', `todo', or `priority'); or a user-defined comparator +function that accepts two items as arguments and returns nil or +non-nil." (declare (indent defun)) (-let* ((buffers (->> (cl-typecase buffers-or-files (null (list (current-buffer))) @@ -197,6 +201,8 @@ a list of defined `org-ql' sorting methods: `date', `deadline', always (memq elem '(date deadline scheduled todo priority))))) ;; Default sorting functions (org-ql--sort-by items sort)) + ;; Sort by user-given comparator. + ((pred functionp) (sort items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) (defun org-ql--query-predicate (query) From ad6624d9aea189b3c9e00dc2cf0fe5c029fe156b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 22 Jul 2019 14:42:46 -0500 Subject: [PATCH 212/970] Comment: Add FIXME --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index 363b8de..9782f3e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -293,6 +293,7 @@ replace the clause with a preamble." (setq org-ql-preamble regexp) ;; Return nil nil)) + ;; FIXME: Need to handle e.g. (level <= 2) (`(level ,num) (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ")))) (setq org-ql-preamble regexp) From dbb94ff3b8c88e47d9aea1822cbd6fdfb2e41cc3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 19:01:16 -0500 Subject: [PATCH 213/970] Tests: Use xr to help format test results --- Cask | 4 +++- tests/test-org-ql.el | 30 ++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Cask b/Cask index a78c6fa..7afe920 100644 --- a/Cask +++ b/Cask @@ -2,7 +2,9 @@ (files "org-ql.el" "org-ql-agenda.el") +(source gnu) (source melpa) (development - (depends-on "buttercup")) + (depends-on "buttercup") + (depends-on "xr")) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 80663ec..e2e3110 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -35,16 +35,30 @@ "FIXME: docstring" (interactive) (if-let* ((sexp (elisp--preceding-sexp)) - (correct-sexp-p (eq (car sexp) 'org-ql)) - (value (eval sexp)) - (prefix (if (and value (listp value)) - "'" - ""))) - (insert " :to-equal " - prefix - (format "%S" value)) + (correct-sexp-p (pcase (car sexp) + ('org-ql 'org-ql) + ('org-ql--query-preamble 'query-preamble) + (_ nil))) + (result (pcase (car sexp) + ('org-ql (org-ql-test--format-result--ql sexp)) + ('org-ql--query-preamble (org-ql-test--format-result--query-preamble sexp)) + (_ nil)))) + (insert " :to-equal " result) (user-error "Point must be after an `org-ql' form"))) +(defun org-ql-test--format-result--ql (sexp) + (let* ((value (eval sexp)) + (prefix (if (and value (listp value)) + "'" + ""))) + (format "%S" value))) + +(defun org-ql-test--format-result--query-preamble (sexp) + (-let* (((query preamble) (eval sexp)) + (preamble (when preamble + (xr preamble 'brief)))) + (format "`(%S ,(rx %S))" query preamble))) + (defun org-ql-test-show-result () "Show `org-ql-agenda' for `org-ql' form." (interactive) From 99b38d131e2fd10cbf613fb650fef48650d0d822 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 19:03:33 -0500 Subject: [PATCH 214/970] Tests: Add org-ql-it macro Tests with and without preamble, ensuring they give the same results. Very important. And macros make this so easy to do. --- tests/test-org-ql.el | 62 ++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index e2e3110..427a30d 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -69,6 +69,24 @@ (eval sexp)) (user-error "Point must be after an `org-ql' form"))) +;;;; Macros + +(defmacro org-ql-it (description &rest body) + "Expand to two specs, one of which tests with preambles and the other without. +Based on Buttercup macro `it'." + (declare (indent 1) (debug (&define sexp def-body))) + (if body + `(progn + (buttercup-it ,(concat description " (preamble) ") + (lambda () + (let ((org-ql-use-preamble t)) + ,@body))) + (buttercup-it ,(concat description " (no preamble)") + (lambda () + (let ((org-ql-use-preamble nil)) + ,@body)))) + `(buttercup-xit ,description))) + ;;;; Tests (describe "org-ql" @@ -92,24 +110,24 @@ (describe "Predicates" (describe "(category)" - (it "without arguments" + (org-ql-it "without arguments" (expect (length (org-ql test-buffer (category) :action (org-ql-test-org-get-heading))) :to-equal num-headings)) - (it "with a category" + (org-ql-it "with a category" (expect (org-ql test-buffer (category "ambition") :action (org-ql-test-org-get-heading)) :to-equal '("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 "(clocked)" - (it "without arguments" + (org-ql-it "without arguments" (expect (org-ql test-buffer (clocked) :action (org-ql-test-org-get-heading)) :to-equal '("Learn universal sign language"))) - (it ":from a timestamp" + (org-ql-it ":from a timestamp" (expect (org-ql test-buffer (clocked :from "2017-07-05") :action (org-ql-test-org-get-heading)) @@ -118,7 +136,7 @@ (clocked :from "2017-07-06") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ":to a timestamp" + (org-ql-it ":to a timestamp" (expect (org-ql test-buffer (clocked :to "2017-07-05") :action (org-ql-test-org-get-heading)) @@ -127,7 +145,7 @@ (clocked :to "2017-07-04") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ":on a date" + (org-ql-it ":on a date" (expect (org-ql test-buffer (clocked :on "2017-07-05") :action (org-ql-test-org-get-heading)) @@ -136,7 +154,7 @@ (clocked :on "2018-12-02") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it "within a range (:from and :to)" + (org-ql-it "within a range (:from and :to)" (expect (org-ql test-buffer (clocked :from "2017-07-04" :to "2018-12-11") :action (org-ql-test-org-get-heading)) @@ -151,12 +169,12 @@ :to-equal nil))) (describe "(closed)" - (it "without arguments" + (org-ql-it "without arguments" (expect (org-ql test-buffer (closed) :action (org-ql-test-org-get-heading)) :to-equal '("Learn universal sign language"))) - (it "=" + (org-ql-it "=" (expect (org-ql test-buffer (closed = "2017-07-05") :action (org-ql-test-org-get-heading)) @@ -165,7 +183,7 @@ (closed = "2019-06-09") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it "<" + (org-ql-it "<" ;; TODO: Figure out why these tests take about 8 times longer than the other comparators in the (closed) tests. (expect (org-ql test-buffer (closed < "2019-06-10") @@ -175,7 +193,7 @@ (closed < "2017-06-10") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ">" + (org-ql-it ">" (expect (org-ql test-buffer (closed > "2017-07-04") :action (org-ql-test-org-get-heading)) @@ -184,7 +202,7 @@ (closed > "2019-07-05") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ">=" + (org-ql-it ">=" (expect (org-ql test-buffer (closed >= "2017-07-04") :action (org-ql-test-org-get-heading)) @@ -197,7 +215,7 @@ (closed >= "2017-07-06") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it "<=" + (org-ql-it "<=" (expect (org-ql test-buffer (closed <= "2017-07-04") :action (org-ql-test-org-get-heading)) @@ -212,12 +230,12 @@ :to-equal '("Learn universal sign language")))) (describe "(deadline)" - (it "without arguments" + (org-ql-it "without arguments" (expect (org-ql test-buffer (deadline) :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs"))) - (it "=" + (org-ql-it "=" (expect (org-ql test-buffer (deadline = "2017-07-05") :action (org-ql-test-org-get-heading)) @@ -226,7 +244,7 @@ (deadline = "2019-06-09") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it "<" + (org-ql-it "<" (expect (org-ql test-buffer (deadline < "2019-06-10") :action (org-ql-test-org-get-heading)) @@ -235,7 +253,7 @@ (deadline < "2017-06-10") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ">" + (org-ql-it ">" ;; TODO: Figure out why these tests take much longer than e.g. the (deadline <) tests. (expect (org-ql test-buffer (deadline > "2017-07-04 00:00") @@ -245,7 +263,7 @@ (deadline > "2019-07-05") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ">=" + (org-ql-it ">=" (expect (org-ql test-buffer (deadline >= "2017-07-04") :action (org-ql-test-org-get-heading)) @@ -262,7 +280,7 @@ (deadline >= "2018-07-06") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it "<=" + (org-ql-it "<=" (expect (org-ql test-buffer (deadline <= "2017-07-04") :action (org-ql-test-org-get-heading)) @@ -276,7 +294,7 @@ :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")))) - (it "(done)" + (org-ql-it "(done)" (expect (org-ql test-buffer (done) :action (org-ql-test-org-get-heading)) @@ -329,7 +347,7 @@ (ts :from "2019-06-08") :action (org-ql-test-org-get-heading)) :to-equal nil)) - (it ":to a timestamp" + (org-ql-it ":to a timestamp" (expect (org-ql test-buffer (ts :to "2019-06-10") :action (org-ql-test-org-get-heading)) @@ -338,7 +356,7 @@ (ts :to "2017-07-04") :action (org-ql-test-org-get-heading)) :to-equal '("Skype with president of Antarctica"))) - (it ":on a timestamp" + (org-ql-it ":on a timestamp" (expect (org-ql test-buffer (ts :on "2017-07-05") :action (org-ql-test-org-get-heading)) From bdf473356d9f31df88c62803b3f72649f179d5d3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 19:14:01 -0500 Subject: [PATCH 215/970] Change: Improve level predicate Now accepts e.g. (level 2 4) to match headings from levels 2-4, inclusive. Also add tests for (level) preamble conversion. --- README.org | 2 +- org-ql.el | 41 +++++++++++++++++++++++++++-------------- tests/test-org-ql.el | 35 +++++++++++++++++++++++++++++------ 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/README.org b/README.org index 34dde96..693c7f1 100644 --- a/README.org +++ b/README.org @@ -118,7 +118,7 @@ Note that, for convenience, standard numeric comparator function symbols (~<~, ~ + ~done~ :: Return non-nil if entry's ~TODO~ keyword is in ~org-done-keywords~. + ~habit~ :: Return non-nil if entry is a habit. + ~heading (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). -+ ~level (level-or-comparator &optional level)~ :: Return non-nil if current heading's outline level matches ~LEVEL~ with ~COMPARATOR~. If ~LEVEL~ is nil, ~LEVEL-OR-COMPARATOR~ should be an integer level, which will be tested for equality to the heading's outline level. If ~LEVEL~ is non-nil, ~LEVEL-OR-COMPARATOR~ should be a comparator function (like ~<=~). ++ ~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 ~>=~. + ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~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. + ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). diff --git a/org-ql.el b/org-ql.el index 9782f3e..6399d22 100644 --- a/org-ql.el +++ b/org-ql.el @@ -281,7 +281,7 @@ replace the clause with a preamble." (pcase element (`(or _) element) (`(regexp . ,regexps) - (let* ((regexp (rx-to-string `(or ,@regexps)))) + (let* ((regexp (rx-to-string `(or ,@regexps) t))) (setq org-ql-preamble regexp) ;; Return nil nil)) @@ -289,13 +289,21 @@ replace the clause with a preamble." (let* ((regexps (--map (list 'regexp (format org-heading-keyword-regexp-format it)) todo-keywords)) - (regexp (rx-to-string `(or ,@regexps)))) + (regexp (rx-to-string `(or ,@regexps) t))) (setq org-ql-preamble regexp) ;; Return nil nil)) - ;; FIXME: Need to handle e.g. (level <= 2) + (`(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)) + nil)) (`(level ,num) - (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ")))) + (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ") t))) (setq org-ql-preamble regexp) nil)) (`(and . ,rest) @@ -502,20 +510,25 @@ With KEYWORDS, return non-nil if its keyword is one of KEYWORDS (a list of strin (otherwise (seq-intersection tags tags-at))))) (org-ql--defpred level (level-or-comparator &optional level) - "Return non-nil if current heading's outline level matches LEVEL with COMPARATOR. + "Return non-nil if current heading's outline level matches arguments. +The following forms are accepted: -If LEVEL is nil, LEVEL-OR-COMPARATOR should be an integer level, -which will be tested for equality to the heading's outline level. -If LEVEL is non-nil, LEVEL-OR-COMPARATOR should be a comparator -function (like `<=')." + (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 - ;; Check for equality - ((pred null) (= outline-level level-or-comparator)) - ;; Check with comparator - (_ (funcall level-or-comparator outline-level 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 priority (&optional comparator-or-priority priority) "Return non-nil if current heading has a certain priority. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 427a30d..0cb32e3 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -107,7 +107,34 @@ Based on Buttercup macro `it'." (cl-loop while (re-search-forward org-heading-regexp nil t) sum 1))))) - (describe "Predicates" + (describe "Query compiling" + ;; Okay, so it's not really "compiling," but it sounds fancy. :) + + ;; TODO: Other predicates. + + (describe "(level)" + (it "with a number" + (expect (org-ql--query-preamble '(level 2)) + :to-equal `(t ,(rx bol (repeat 2 "*") " ")))) + (it "with two numbers" + (expect (org-ql--query-preamble '(level 2 4)) + :to-equal `(t ,(rx bol (repeat 2 4 "*") " ")))) + (it "<" + (expect (org-ql--query-preamble '(level < 3)) + :to-equal `(t ,(rx bol (repeat 1 2 "*") " ")))) + (it "<=" + (expect (org-ql--query-preamble '(level <= 2)) + :to-equal `(t ,(rx bol (repeat 1 2 "*") " ")))) + (it ">" + (expect (org-ql--query-preamble '(level > 2)) + :to-equal `(t ,(rx bol (>= 3 "*") " ")))) + (it ">=" + (expect (org-ql--query-preamble '(level >= 2)) + :to-equal `(t ,(rx bol (>= 2 "*") " ")))))) + + (describe "Query results" + + ;; TODO: Other predicates. (describe "(category)" (org-ql-it "without arguments" @@ -364,10 +391,6 @@ Based on Buttercup macro `it'." (expect (org-ql test-buffer (ts :on "2019-06-09") :action (org-ql-test-org-get-heading)) - :to-equal nil)) - ) - - ;; TODO: Other predicates. - )) + :to-equal nil))))) ;;; org-ql.el ends here From c19cc4d6d21b2a4c41eb4738d316eed527377732 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 19:16:10 -0500 Subject: [PATCH 216/970] Docs: (README.org) Remove Predicates from ToC --- README.org | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 693c7f1..8c3c1f7 100644 --- a/README.org +++ b/README.org @@ -16,7 +16,6 @@ - [[#usage][Usage]] - [[#commands][Commands]] - [[#queries][Queries]] - - [[#predicates][Predicates]] - [[#functions--macros][Functions / Macros]] - [[#changelog][Changelog]] - [[#notes][Notes]] @@ -105,6 +104,9 @@ Here's an example of using it to generate an agenda-like view for certain files A 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. *** Predicates +:PROPERTIES: +:TOC: ignore +:END: Arguments are listed next to predicate names, where applicable. From 76ba0afebdda25c8eaec26747cf893fe7b10f7b5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 21:14:33 -0500 Subject: [PATCH 217/970] Comment: Add FIXME --- org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql.el b/org-ql.el index 6399d22..f5574b6 100644 --- a/org-ql.el +++ b/org-ql.el @@ -286,6 +286,8 @@ replace the clause with a preamble." ;; Return nil nil)) (`(todo . ,(and todo-keywords (guard todo-keywords))) + ;; FIXME: With case-folding, a query like (todo "WAITING") + ;; can find a non-todo heading named "Waiting". (let* ((regexps (--map (list 'regexp (format org-heading-keyword-regexp-format it)) todo-keywords)) From 6728ddaaa7d00c134eb8dd18a48ce7d6ea5000ad Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 21:25:32 -0500 Subject: [PATCH 218/970] Change: (--query-preamble) Simplify (todo) preamble --- org-ql.el | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index f5574b6..4874030 100644 --- a/org-ql.el +++ b/org-ql.el @@ -288,13 +288,11 @@ replace the clause with a preamble." (`(todo . ,(and todo-keywords (guard todo-keywords))) ;; FIXME: With case-folding, a query like (todo "WAITING") ;; can find a non-todo heading named "Waiting". - (let* ((regexps (--map (list 'regexp - (format org-heading-keyword-regexp-format it)) - todo-keywords)) - (regexp (rx-to-string `(or ,@regexps) t))) - (setq org-ql-preamble regexp) - ;; Return nil - nil)) + (setq org-ql-preamble + (rx-to-string `(seq bol (1+ "*") (1+ space) (or ,@todo-keywords) (or " " eol)) + t)) + ;; Return nil + nil) (`(level ,comparator-or-num ,num) (let ((repeat (pcase comparator-or-num ('< `(repeat 1 ,(1- num) "*")) From 06c7f55b218b0a68ad21aa91c0c5e26d894ea127 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 23 Jul 2019 21:32:44 -0500 Subject: [PATCH 219/970] Change: (--query-preamble) Simplify --- org-ql.el | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/org-ql.el b/org-ql.el index 4874030..8d23add 100644 --- a/org-ql.el +++ b/org-ql.el @@ -281,10 +281,9 @@ replace the clause with a preamble." (pcase element (`(or _) element) (`(regexp . ,regexps) - (let* ((regexp (rx-to-string `(or ,@regexps) t))) - (setq org-ql-preamble regexp) - ;; Return nil - nil)) + (setq org-ql-preamble (rx-to-string `(or ,@regexps) t)) + ;; Return nil + nil) (`(todo . ,(and todo-keywords (guard todo-keywords))) ;; FIXME: With case-folding, a query like (todo "WAITING") ;; can find a non-todo heading named "Waiting". @@ -303,9 +302,8 @@ replace the clause with a preamble." (setq org-ql-preamble (rx-to-string `(seq bol ,repeat " ") t)) nil)) (`(level ,num) - (let* ((regexp (rx-to-string `(seq bol (repeat ,num "*") " ") t))) - (setq org-ql-preamble regexp) - nil)) + (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) + nil) (`(and . ,rest) (let ((clauses (mapcar #'rec rest))) `(and ,@(-non-nil clauses)))) From 3b9c47419347091fb02d1935298c196ff1abcf5a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 00:44:38 -0500 Subject: [PATCH 220/970] Fix: (org-ql-query) Don't byte-compile compiled functions --- org-ql.el | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 8d23add..1fcd939 100644 --- a/org-ql.el +++ b/org-ql.el @@ -179,8 +179,13 @@ non-nil." (user-error "Can't open file: %s" it))))))) ((query preamble-re) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) - ;; FIXME: Don't try to byte-compile already-compiled functions. - (action (byte-compile action)) + (action (cl-etypecase action + (symbol (unless (functionp action) + (user-error "Action not a function: %s" action)) + action) + (function (byte-compile action)) + (list (byte-compile `(lambda (&rest _ignore) + ,action))))) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) From 7c4297b667e36599435f4958c606756ad270819d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 01:29:33 -0500 Subject: [PATCH 221/970] Add/Change: (org-ql-select, org-ql-query) Add/rename function Also improve docstrings. --- README.org | 111 +++++++++++++++++++++++++++++++-------- org-ql-agenda.el | 2 +- org-ql.el | 133 +++++++++++++++++++++++++---------------------- 3 files changed, 163 insertions(+), 83 deletions(-) diff --git a/README.org b/README.org index 8c3c1f7..cc68153 100644 --- a/README.org +++ b/README.org @@ -59,12 +59,12 @@ More examples are available in [[examples.org]]. The functionality provided may be grouped by: + Interactive commands :: ~org-ql-search~ -+ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-query~ (function), and ~org-ql-agenda~ (macro) ++ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-select~ (function), ~org-ql-query~ (function), and ~org-ql-agenda~ (macro) Alternatively, they may be grouped by: + Showing an agenda-like view :: ~org-ql-search~ (command), and ~org-ql-agenda~ (macro) -+ Returning a list of matches or acting on them :: ~org-ql~ (macro), and ~org-ql-query~ (function) ++ Returning a list of matches or acting on them :: ~org-ql~ (macro), ~org-ql-select~ (function), and ~org-ql-query~ (function) Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -198,41 +198,105 @@ Here are some other examples: *** Listing / acting-on results -**** Function: ~org-ql-query~ +**** 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) file(s) or buffer(s). +~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. For example, ~org-element-headline-parser~ may be used to parse an entry into an Org element (note that it must be called with a limit argument, so a lambda must be used to do so). Also see ~org-ql--add-markers~, which may be used to add markers compatible with Org Agenda code. +~ACTION~ is a function which is called on each matching entry with point at the beginning of its heading. It may be: -If ~NARROW~ is non-nil, buffers are not widened. + - ~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~, or ~priority~); or a user-defined comparator function that accepts two items as arguments and returns nil or non-nil. +Examples: + +#+BEGIN_SRC elisp + ;; 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" ...) ...) ...) +#+END_SRC + +**** Function: ~org-ql-query~ + +/Arguments:/ ~(&key (select 'element-with-markers) from where)~ + +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~. + +Examples: + +#+BEGIN_SRC elisp + ;; 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" ...) ...) ...) +#+END_SRC + **** Macro: ~org-ql~ /Arguments:/ ~(buffers-or-files query &key sort narrow markers action)~ -Find entries in ~BUFFERS-OR-FILES~ that match ~QUERY~, and return the results of running ~ACTION-FN~ on each matching entry. - -Unlike the corresponding function ~org-ql-query~, arguments to this macro should not be quoted. - -~BUFFERS-OR-FILES~ is a form which should evaluate to one (or a list of) file(s) or buffer(s). - -~QUERY~ is an ~org-ql~ query sexp, unquoted. - -~ACTION~ is a sexp which will be evaluated at each matching entry with point at the beginning of its heading. It is passed to ~org-ql-query~ as a lambda. By default, ~org-element-headline-parser~ is called to return an Org element. - -~SORT~ is a user defined sorting function, or an unquoted list of one or more sorting methods, including: ~date~, ~deadline~, ~scheduled~, ~todo~, and ~priority~. - -If ~NARROW~ is non-nil, query will run without widening the buffer (the default is to widen and search the entire buffer). - -If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to each item, pointing to the item in its source buffer. In this case, ~ACTION~ should return an Org element. +Expands into a call to ~org-ql-select~ with the same arguments. For convenience, arguments should be unquoted. * Changelog :PROPERTIES: @@ -243,7 +307,12 @@ If ~MARKERS~ is non-nil, ~org-agenda-ng--add-markers~ is used to add markers to ** 0.2-pre +*Added* ++ Function ~org-ql-query~, like ~org-ql-select~ but with arguments named more like a SQL query. + *Changed* ++ Function ~org-ql-query~ renamed to ~org-ql-select~. ++ 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. + ~(regexp)~ selector accepts multiple regexps to test. + The ~:sort~ argument to ~org-ql~, ~org-ql-query~, etc. now also accepts a comparator function by which to sort items. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index d0e4a67..f17e069 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -207,7 +207,7 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (when (and super-groups (not org-super-agenda-mode)) (user-error "`org-super-agenda-mode' must be activated to use grouping")) (let* ((org-super-agenda-groups super-groups) - (entries (--> (org-ql-query buffers-files + (entries (--> (org-ql-select buffers-files query :sort sort :narrow narrow diff --git a/org-ql.el b/org-ql.el index 1fcd939..a680080 100644 --- a/org-ql.el +++ b/org-ql.el @@ -91,48 +91,13 @@ match." (push (list :name ',pred-name :fn ',fn-name :docstring ,docstring :args ',args) org-ql-predicates) (cl-defun ,fn-name ,args ,docstring ,@body)))) -(cl-defmacro org-ql (buffers-or-files query &key sort narrow markers - (action '(org-element-headline-parser (line-end-position)))) - "Find entries in BUFFERS-OR-FILES that match QUERY, and return the results of running ACTION-FN on each matching entry. - -Unlike the corresponding function `org-ql-query', arguments to -this macro should not be quoted. - -BUFFERS-OR-FILES is a form which should evaluate to one (or a -list of) file(s) or buffer(s). - -QUERY is an `org-ql' query sexp, unquoted. - -ACTION is a sexp which will be evaluated at each matching entry -with point at the beginning of its heading. It is passed to -`org-ql-query' as a lambda. By default, `org-element-headline-parser' - is called to return an Org element. - -SORT is either nil, in which case items are not sorted; or one or -a list of predefined `org-ql' sorting methods (`date', `deadline', -`scheduled', `todo', or `priority'; or a user-defined comparator -function that accepts two items as arguments and returns nil or -non-nil. - -If NARROW is non-nil, query will run without widening the -buffer (the default is to widen and search the entire buffer). - -If MARKERS is non-nil, `org-ql--add-markers' is used to -add markers to each item, pointing to the item in its source -buffer. In this case, ACTION should return an Org element." +(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)) - (setq action (pcase markers - ('nil `(lambda () - ,action)) - (_ `(lambda () - ;; FIXME: Document that, when markers is t, `action' should return an Org - ;; headline element, which --add-markers works with. On the other hand, - ;; maybe this should be on the agenda-ng side. - (->> ,action - org-ql--add-markers))))) - `(org-ql-query ,buffers-or-files + `(org-ql-select ,buffers-or-files ',query - :action ,action + :action ',action :narrow ,narrow :sort ',sort)) @@ -141,23 +106,31 @@ buffer. In this case, ACTION should return an Org element." (define-hash-table-test 'org-ql-hash-test #'equal (lambda (args) (sxhash-equal (prin1-to-string args)))) -(cl-defun org-ql-query (buffers-or-files query &key action narrow sort) +(cl-defun org-ql-select (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) file(s) or buffer(s). +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. For example, -`org-element-headline-parser' may be used to parse an entry into -an Org element (note that it must be called with a limit -argument, so a lambda must be used to do so). Also see -`org-ql--add-markers', which may be used to add markers -compatible with Org Agenda code. +ACTION is a function which is called on each matching entry with +point at the beginning of its heading. It may be: -If NARROW is non-nil, buffers are not widened. +- `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', @@ -179,13 +152,23 @@ non-nil." (user-error "Can't open file: %s" it))))))) ((query preamble-re) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) - (action (cl-etypecase action - (symbol (unless (functionp action) - (user-error "Action not a function: %s" action)) - action) - (function (byte-compile action)) - (list (byte-compile `(lambda (&rest _ignore) - ,action))))) + (action (pcase action + ;; NOTE: These two lambdas are backquoted to prevent "unused lexical + ;; variable" warnings from byte-compilation, because they don't use + ;; all of the variables from their enclosing scope. + ('element-with-markers (byte-compile + `(lambda (&rest _ignore) + (org-ql--add-markers + (org-element-headline-parser (line-end-position)))))) + ((or 'nil 'element) (byte-compile + `(lambda (&rest _ignore) + (org-element-headline-parser (line-end-position))))) + ((pred functionp) action) + ((and (pred listp) (guard (functionp (car action)))) + (byte-compile + `(lambda (&rest _ignore) + ,action))) + (_ (user-error "Invalid action form: %s" action)))) ;; TODO: Figure out how to use or reimplement the org-scanner-tags feature. ;; (org-use-tag-inheritance t) ;; (org-trust-scanner-tags t) @@ -210,6 +193,34 @@ non-nil." ((pred functionp) (sort items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) +(cl-defun org-ql-query (&key (select 'element-with-markers) from where) + "Like `org-ql-select', but arguments are named more like a SQL query. + +SELECT corresponds to the `org-ql-select' argument ACTION. It is +the function called on matching headings, the results of which +are returned by this function. It may be: + +- `element' or nil: Equivalent to `org-element-headline-parser'. + +- `element-with-markers': Equivalent to + `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. + +FROM corresponds to the `org-ql-select' argument BUFFERS-OR-FILES. +It may be one or a list of file paths and/or buffers. + +WHERE corresponds to the `org-ql-select' argument QUERY. It +should be an `org-ql' query sexp." + (declare (indent defun)) + (org-ql-select from where + :action select)) + (defun org-ql--query-predicate (query) "Return predicate function for QUERY." (byte-compile `(lambda () @@ -460,7 +471,7 @@ Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored." ;; 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-query'. + ;; 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-clock-line-re end-pos t) @@ -626,7 +637,7 @@ 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-query'. + ;; 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) @@ -668,7 +679,7 @@ 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-query'. + ;; 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) @@ -711,7 +722,7 @@ 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-query'. + ;; 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) From 70176d9c5fff9917d392be4c19e3d32716d21055 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 20:15:52 -0500 Subject: [PATCH 222/970] Add: Convert bare strings to (regexp) predicates --- README.org | 7 +++++-- org-ql.el | 18 ++++++++++++++++++ tests/test-org-ql.el | 38 +++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index cc68153..64c473b 100644 --- a/README.org +++ b/README.org @@ -103,6 +103,10 @@ Here's an example of using it to generate an agenda-like view for certain files A 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 these predicates. The resemblance to infix notation is coincidental. See examples in documentation. + *** Predicates :PROPERTIES: :TOC: ignore @@ -110,8 +114,6 @@ A query is a lisp form which may contain arbitrary lisp forms, as well as certai Arguments are listed next to predicate names, where applicable. -Note that, for convenience, standard numeric comparator function symbols (~<~, ~=~, etc.) do not need to be quoted when passed as an argument to these predicates. The resemblance to infix notation is coincidental. See examples in documentation. - + ~category (&optional categories)~ :: Return non-nil if current heading is in one or more of ~CATEGORIES~ (a list of strings). + ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). @@ -309,6 +311,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *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. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. diff --git a/org-ql.el b/org-ql.el index a680080..2abeaa3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -150,6 +150,7 @@ non-nil." ;; a buffer if the filename doesn't exist. (find-file-noselect it)) (user-error "Can't open file: %s" it))))))) + (query (org-ql--pre-process-query query)) ((query preamble-re) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) (action (pcase action @@ -221,6 +222,23 @@ should be an `org-ql' query sexp." (org-ql-select from where :action select)) +(defun org-ql--pre-process-query (query) + "Return QUERY having been pre-processed. +Replaces bare strings with (regexp) selectors." + ;; This is unsophisticated, but it works. + (cl-labels ((rec (element) + (pcase element + (`(or . ,clauses) `(or ,@(mapcar #'rec clauses))) + (`(and . ,clauses) `(and ,@(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)) + (_ element)))) + (rec query))) + (defun org-ql--query-predicate (query) "Return predicate function for QUERY." (byte-compile `(lambda () diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 0cb32e3..835b93b 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -38,10 +38,12 @@ (correct-sexp-p (pcase (car sexp) ('org-ql 'org-ql) ('org-ql--query-preamble 'query-preamble) + ('org-ql--pre-process-query t) (_ nil))) (result (pcase (car sexp) ('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))) (_ nil)))) (insert " :to-equal " result) (user-error "Point must be after an `org-ql' form"))) @@ -107,6 +109,27 @@ Based on Buttercup macro `it'." (cl-loop while (re-search-forward org-heading-regexp nil t) sum 1))))) + (it "Query pre-processing" + (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")) + :to-equal '(or (regexp "string1") (regexp "string2"))) + (expect (org-ql--pre-process-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"))) + :to-equal '(when (todo "TODO") (or (regexp "string1") (regexp "string2")))) + (expect (org-ql--pre-process-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"))) + :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"))) + :to-equal '(unless (and (regexp "stringcondition1") (regexp "stringcond2")) (or (regexp "string1") (regexp "string2"))))) + (describe "Query compiling" ;; Okay, so it's not really "compiling," but it sounds fancy. :) @@ -337,7 +360,20 @@ Based on Buttercup macro `it'." (expect (org-ql test-buffer (regexp "Take over" "pizza") :sort todo - :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut"))) + (org-ql-it "with a plain string" + (expect (org-ql test-buffer + "Take over" + :sort todo + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) + (org-ql-it "with two plain strings" + (expect (org-ql test-buffer + (or "Take over" "pizza") + :sort todo + :action (org-ql-test-org-get-heading)) + :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) (describe "(todo)" (it "without arguments" From 3a9b32002e09a4d6e7c081e17c694132478aa698 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 20:18:41 -0500 Subject: [PATCH 223/970] Docs: Clarify changelog entries --- README.org | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.org b/README.org index 64c473b..edb7054 100644 --- a/README.org +++ b/README.org @@ -312,12 +312,12 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *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. *Changed* -+ Function ~org-ql-query~ renamed to ~org-ql-select~. ++ 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. -+ ~(regexp)~ selector accepts multiple regexps to test. -+ The ~:sort~ argument to ~org-ql~, ~org-ql-query~, etc. now also accepts a comparator function by which to sort items. *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) From 290e25509b2f17281195c5217ff9ad851d01ff63 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 20:20:04 -0500 Subject: [PATCH 224/970] Tests: Use org-ql-it in more tests --- tests/test-org-ql.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 835b93b..ba30eec 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -351,12 +351,12 @@ Based on Buttercup macro `it'." :to-equal '("Learn universal sign language"))) (describe "(regexp)" - (it "with 1 argument" + (org-ql-it "with 1 argument" (expect (org-ql test-buffer (regexp "Take over") :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Get haircut"))) - (it "with 2 arguments" + (org-ql-it "with 2 arguments" (expect (org-ql test-buffer (regexp "Take over" "pizza") :sort todo @@ -376,31 +376,31 @@ Based on Buttercup macro `it'." :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) (describe "(todo)" - (it "without arguments" + (org-ql-it "without arguments" ;; FIXME: This returns an item that is done, which is incorrect. (expect (org-ql test-buffer (todo) :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("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"))) - (it "with 1 argument" + (org-ql-it "with 1 argument" ;; FIXME: Figure out why this takes >10x longer than the other (todo) tests, according to Buttercup. (expect (org-ql test-buffer (todo "WAITING") :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon"))) - (it "with 2 arguments" + (org-ql-it "with 2 arguments" (expect (org-ql test-buffer (todo "WAITING" "SOMEDAY") :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) (describe "(ts)" - (it "without arguments" + (org-ql-it "without arguments" (expect (org-ql test-buffer (ts) :action (org-ql-test-org-get-heading)) :to-equal '("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"))) - (it ":from a timestamp" + (org-ql-it ":from a timestamp" ;; TODO: Figure out why these take longer than the other (ts) tests. (expect (org-ql test-buffer (ts :from "2017-01-01") From 81ef7adbcaee9a705716089118f66faf84d209f2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 24 Jul 2019 20:21:06 -0500 Subject: [PATCH 225/970] Tests: Change description --- tests/test-org-ql.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index ba30eec..67d92be 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -130,8 +130,7 @@ Based on Buttercup macro `it'." (or "string1" "string2"))) :to-equal '(unless (and (regexp "stringcondition1") (regexp "stringcond2")) (or (regexp "string1") (regexp "string2"))))) - (describe "Query compiling" - ;; Okay, so it's not really "compiling," but it sounds fancy. :) + (describe "Query optimizing" ;; TODO: Other predicates. From b5ccc3294ec7942fa6a7eb041208b2b28c23ecd6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 25 Jul 2019 07:51:28 -0500 Subject: [PATCH 226/970] Fix: (--select) Don't iterate over every heading with preamble Oops, using "when" instead of "while" did outline-next-heading even when re-search-forward found no more matches. That unnecessarily slowed down some searches, negating almost all of the gains. --- org-ql.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/org-ql.el b/org-ql.el index 2abeaa3..bb6e726 100644 --- a/org-ql.el +++ b/org-ql.el @@ -404,10 +404,11 @@ If NARROW is non-nil, buffer will not be widened." (goto-char (point-min)) (when (org-before-first-heading-p) (outline-next-heading)) - (cond (preamble-re (cl-loop when (and (when (re-search-forward preamble-re nil t) - (outline-back-to-heading 'invisible-ok) - t) - (funcall predicate)) + ;; `cl-loop' makes this double-while much clearer than the expanded form. + (cond (preamble-re (cl-loop while (and (when (re-search-forward preamble-re nil t) + (outline-back-to-heading 'invisible-ok) + t) + (funcall predicate)) collect (funcall action) while (outline-next-heading))) (t (cl-loop when (funcall predicate) From cc5756d00dab1613572339e7dbf3544ad23391cb Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 25 Jul 2019 21:55:49 -0500 Subject: [PATCH 227/970] Add: (org-ql-agenda--header-line-format) Move code to new function --- org-ql-agenda.el | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index f17e069..0560edc 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -230,25 +230,9 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (setq-local org-ql-sort sort) (setq-local org-ql-narrow narrow) (setq-local org-ql-super-groups super-groups) + (setq-local header-line-format (org-ql-agenda--header-line-format buffers-files query)) ;; TODO: Derive a minor mode and set keymap there. (local-set-key "g" #'org-ql-search-refresh) - (let* ((query-formatted (format "%S" query)) - (query-formatted (propertize (org-ql-agenda--font-lock-string 'emacs-lisp-mode query-formatted) - 'help-echo query-formatted)) - (query-width (length query-formatted)) - (available-width (- (window-width) - (length "In: ") - (length "Query: ") - query-width 4)) - (buffers-files-formatted (format "%S" buffers-files)) - (buffers-files-formatted (propertize (->> buffers-files-formatted - (org-ql-agenda--font-lock-string 'emacs-lisp-mode) - (s-truncate available-width)) - 'help-echo buffers-files-formatted))) - (setq-local header-line-format (concat (propertize "Query: " 'face 'org-agenda-structure) - query-formatted " " - (propertize "In: " 'face 'org-agenda-structure) - buffers-files-formatted))) ;; Clear buffer, insert entries, etc. (erase-buffer) (insert entries) @@ -256,6 +240,26 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (org-agenda-finalize) (goto-char (point-min))))) +(defun org-ql-agenda--header-line-format (buffers-files query) + "Return header-line-format for BUFFERS-FILES and QUERY." + (let* ((query-formatted (format "%S" query)) + (query-formatted (propertize (org-ql-agenda--font-lock-string 'emacs-lisp-mode query-formatted) + 'help-echo query-formatted)) + (query-width (length query-formatted)) + (available-width (- (window-width) + (length "In: ") + (length "Query: ") + query-width 4)) + (buffers-files-formatted (format "%S" buffers-files)) + (buffers-files-formatted (propertize (->> buffers-files-formatted + (org-ql-agenda--font-lock-string 'emacs-lisp-mode) + (s-truncate available-width)) + 'help-echo buffers-files-formatted))) + (concat (propertize "Query: " 'face 'org-agenda-structure) + query-formatted " " + (propertize "In: " 'face 'org-agenda-structure) + buffers-files-formatted))) + (defun org-ql-agenda--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 5f60bed1ac44d74b900bf25f97d616b6646213e7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 26 Jul 2019 02:12:11 -0500 Subject: [PATCH 228/970] Notes: Update bench macro --- notes.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notes.org b/notes.org index 4a390fc..281f665 100644 --- a/notes.org +++ b/notes.org @@ -417,9 +417,9 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled `(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-query ,file + :forms ((,(prin1-to-string query) (org-ql-select ,file ',query - :action (lambda () (org-get-heading t t))))))) + :action '(org-get-heading t t)))))) #+END_SRC *** =level= From 8a8b74f1412660515534157c5622009d6b3c06b3 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 26 Jul 2019 02:12:32 -0500 Subject: [PATCH 229/970] Add: (tags) Preamble and tests Only enabled when org-use-tag-inheritance is enabled. --- notes.org | 30 ++++++++++++++++++++++++++++++ org-ql.el | 8 ++++++++ tests/test-org-ql.el | 29 +++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/notes.org b/notes.org index 281f665..e9f1a14 100644 --- a/notes.org +++ b/notes.org @@ -436,6 +436,36 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled | preamble: (level 1) | 1.34 | 0.562950 | 0 | 0 | | no preamble: (level 1) | slowest | 0.754050 | 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 | + ** 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. diff --git a/org-ql.el b/org-ql.el index bb6e726..4c26b3c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -338,6 +338,14 @@ replace the clause with a preamble." (`(level ,num) (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) nil) + ((and `(tags . ,tags) (guard (not org-use-tag-inheritance))) + ;; When tag inheritance is disabled, we only consider direct tags, + ;; so 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) (`(and . ,rest) (let ((clauses (mapcar #'rec rest))) `(and ,@(-non-nil clauses)))) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 67d92be..9f7e5d8 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -393,6 +393,35 @@ Based on Buttercup macro `it'." :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon" "Rewrite Emacs in Common Lisp" "Write a symphony")))) + (describe "(tags)" + (org-ql-it "without arguments" + (expect (org-ql test-buffer + (tags) + :action (org-ql-test-org-get-heading)) + :to-equal '("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")) + (expect (org-ql test-buffer + (not (tags)) + :action (org-ql-test-org-get-heading)) + :to-equal '("Test data" "Recurring" "Sunrise/sunset" "Ideas" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + (org-ql-it "with a tag" + (expect (org-ql test-buffer + (tags "Emacs") + :action (org-ql-test-org-get-heading)) + :to-equal '("/r/emacs" "Rewrite Emacs in Common Lisp")) + (expect (org-ql test-buffer + (not (tags "Emacs")) + :action (org-ql-test-org-get-heading)) + :to-equal '("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"))) + (org-ql-it "with 2 tags" + (expect (org-ql test-buffer + (tags "Emacs" "space") + :action (org-ql-test-org-get-heading)) + :to-equal '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) + (expect (org-ql test-buffer + (not (tags "Emacs" "space")) + :action (org-ql-test-org-get-heading)) + :to-equal '("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")))) + (describe "(ts)" (org-ql-it "without arguments" (expect (org-ql test-buffer From f8a5dc353d62c66d18e9f8006df7eeb3d17e18c6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 26 Jul 2019 02:13:32 -0500 Subject: [PATCH 230/970] Comment: Add/improve some comments --- org-ql.el | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/org-ql.el b/org-ql.el index 4c26b3c..1764efb 100644 --- a/org-ql.el +++ b/org-ql.el @@ -316,15 +316,17 @@ replace the clause with a preamble." (`(or _) element) (`(regexp . ,regexps) (setq org-ql-preamble (rx-to-string `(or ,@regexps) t)) - ;; Return nil + ;; Return nil, because we don't need to test the predicate. nil) (`(todo . ,(and todo-keywords (guard todo-keywords))) - ;; FIXME: With case-folding, a query like (todo "WAITING") - ;; can find a non-todo heading named "Waiting". + ;; FIXME: With case-folding, a query like (todo "WAITING") can find a non-todo + ;; heading named "Waiting". For correctness, we could test the predicate + ;; anyway, but that would negate some of the speed, and in most cases it + ;; probably won't matter, so I'm leaving it this way for now. (setq org-ql-preamble (rx-to-string `(seq bol (1+ "*") (1+ space) (or ,@todo-keywords) (or " " eol)) t)) - ;; Return nil + ;; Return nil, don't test the predicate. nil) (`(level ,comparator-or-num ,num) (let ((repeat (pcase comparator-or-num @@ -334,6 +336,7 @@ replace the clause with a preamble." ('>= `(>= ,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)) From f8a9ae75e2ce7fae9d1be8240a2c56eb58e04dce Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 26 Jul 2019 02:14:04 -0500 Subject: [PATCH 231/970] Notes: Add MAYBE --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index e9f1a14..9694dd2 100644 --- a/notes.org +++ b/notes.org @@ -178,6 +178,10 @@ If your function needs to retrieve the tags including inherited tags at the *cur Because the existing ones only search the special date property line. +** MAYBE 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 Byte-compile lambdas CLOSED: [2018-05-09 Wed 17:30] :LOGBOOK: From 51af2a16a7944f1b902a7fcfb39ae4018da30330 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 26 Jul 2019 02:18:21 -0500 Subject: [PATCH 232/970] Tests: Turn on truncate-lines and add to comment --- tests/test-org-ql.el | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 9f7e5d8..1a01be9 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -382,7 +382,8 @@ Based on Buttercup macro `it'." :sort todo :action (org-ql-test-org-get-heading)) :to-equal '("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-it "with 1 argument" - ;; FIXME: Figure out why this takes >10x longer than the other (todo) tests, according to Buttercup. + ;; FIXME: Figure out why this takes >10x longer than the other (todo) + ;; tests, according to Buttercup. Might just be GC, though. (expect (org-ql test-buffer (todo "WAITING") :sort todo @@ -457,4 +458,8 @@ Based on Buttercup macro `it'." :action (org-ql-test-org-get-heading)) :to-equal nil))))) +;; Local Variables: +;; truncate-lines: t +;; End: + ;;; org-ql.el ends here From 7e5cb3303114062050bcee139c7c52b7c57421cc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 08:28:10 -0500 Subject: [PATCH 233/970] Tests: Require buttercup Makes it easier to run interactively by eval'ing the buffer. --- tests/test-org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 1a01be9..9acca2d 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -25,6 +25,8 @@ ;;;; Requirements +(require 'buttercup) + (require 'org-ql) ;;;; Variables From 4db4e411a0b2b4beb10c552dbdee4ec28b1334dc Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 08:28:40 -0500 Subject: [PATCH 234/970] Tests: Fix function definer Works correctly interactively now. --- tests/test-org-ql.el | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 9acca2d..afd2b02 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -97,12 +97,13 @@ Based on Buttercup macro `it'." (before-all - (defun org-ql-test-org-get-heading () - ;; For Org 9.0.5. - (substring-no-properties (org-get-heading t t))) - (defun org-ql-test-org-get-heading () - ;; For Org 9.1.9. - (substring-no-properties (org-get-heading t t t t))) + (if (version< (org-version) "9.1") + (defun org-ql-test-org-get-heading () + ;; For Org 9.0.5. + (substring-no-properties (org-get-heading t t))) + (defun org-ql-test-org-get-heading () + ;; 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")) num-headings (with-current-buffer test-buffer From c4531b25a44e574a97af55840bba556f58983585 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 08:29:26 -0500 Subject: [PATCH 235/970] Fix: Compound queries with preamble Bug was introduced in b5ccc32. --- org-ql.el | 9 ++++----- tests/test-org-ql.el | 11 ++++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/org-ql.el b/org-ql.el index 1764efb..3c323d2 100644 --- a/org-ql.el +++ b/org-ql.el @@ -416,12 +416,11 @@ If NARROW is non-nil, buffer will not be widened." (when (org-before-first-heading-p) (outline-next-heading)) ;; `cl-loop' makes this double-while much clearer than the expanded form. - (cond (preamble-re (cl-loop while (and (when (re-search-forward preamble-re nil t) - (outline-back-to-heading 'invisible-ok) - t) - (funcall predicate)) + (cond (preamble-re (cl-loop while (re-search-forward preamble-re nil t) + do (outline-back-to-heading 'invisible-ok) + when (funcall predicate) collect (funcall action) - while (outline-next-heading))) + do (outline-next-heading))) (t (cl-loop when (funcall predicate) collect (funcall action) while (outline-next-heading))))))) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index afd2b02..0925ba6 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -459,7 +459,16 @@ Based on Buttercup macro `it'." (expect (org-ql test-buffer (ts :on "2019-06-09") :action (org-ql-test-org-get-heading)) - :to-equal nil))))) + :to-equal nil))) + + (describe "Compound queries" + + (org-ql-it "Tags and to-do" + (expect (org-ql test-buffer + (and (todo "SOMEDAY") + (tags "Emacs")) + :action (org-ql-test-org-get-heading)) + :to-equal '("Rewrite Emacs in Common Lisp")))))) ;; Local Variables: ;; truncate-lines: t From b7932063a0a8170eb9b0326c35c20f4495f5c8d9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 08:30:53 -0500 Subject: [PATCH 236/970] Fix: (org-ql-agenda--format-element) Extra indentation --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 0560edc..79dda2e 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -352,7 +352,7 @@ Its property list should be the second item in the list, as returned by `org-ele (due-string (pcase (org-element-property :relative-due-date element) ('nil "") (string (format " %s " (org-add-props string nil 'face 'underline))))) - (string (s-join " " (list todo-keyword priority-string title due-string tag-string)))) + (string (s-join " " (-non-nil (list todo-keyword priority-string title due-string tag-string))))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string (--> string From d37f7c3eeade3a8db91c76ef75ba8dcb15440f29 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 09:03:10 -0500 Subject: [PATCH 237/970] Fix: (org-ql-agenda--agenda) Don't overwrite org-agenda-mode-map --- README.org | 1 + org-ql-agenda.el | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index edb7054..a12c93f 100644 --- a/README.org +++ b/README.org @@ -321,6 +321,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) ++ Don't overwrite bindings in =org-agenda-mode-map=. *Compatibility* + Fixes for compatibility with Org 9.2. (Thanks to [[https://github.com/ataias][Ataias Pereira Reis]] and [[https://github.com/dakra][Daniel Kraus]].) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 79dda2e..1bdcb6e 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -222,8 +222,11 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (string (org-ql-agenda--buffer buffer)) (null (org-ql-agenda--buffer buffer)) (buffer buffer))) + (map (copy-keymap org-agenda-mode-map)) (inhibit-read-only t)) + (define-key map "g" #'org-ql-search-refresh) (with-current-buffer buffer + (use-local-map map) ;; Prepare buffer, saving data for refreshing. (setq-local org-ql-buffers-files buffers-files) (setq-local org-ql-query query) @@ -231,8 +234,6 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (setq-local org-ql-narrow narrow) (setq-local org-ql-super-groups super-groups) (setq-local header-line-format (org-ql-agenda--header-line-format buffers-files query)) - ;; TODO: Derive a minor mode and set keymap there. - (local-set-key "g" #'org-ql-search-refresh) ;; Clear buffer, insert entries, etc. (erase-buffer) (insert entries) From bd56652c6607d9852ebaa629e6850aaf867c99b0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 09:34:05 -0500 Subject: [PATCH 238/970] Add: org-ql-block Usable as an Org Agenda custom command block type. Inspired by @pestctrl's custom config: https://github.com/pestctrl/emacs-config/blob/84c557982a860e86d6f67976a82ea776a7bd2c7a/config-org-new.org#my-own-agenda-renderer --- README.org | 29 +++++++++++++++++++++++++++-- org-ql-agenda.el | 27 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/README.org b/README.org index a12c93f..cc371be 100644 --- a/README.org +++ b/README.org @@ -59,11 +59,11 @@ More examples are available in [[examples.org]]. The functionality provided may be grouped by: + Interactive commands :: ~org-ql-search~ -+ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-select~ (function), ~org-ql-query~ (function), and ~org-ql-agenda~ (macro) ++ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-select~ (function), ~org-ql-query~ (function), ~org-ql-block~ (agenda function), and ~org-ql-agenda~ (macro) Alternatively, they may be grouped by: -+ Showing an agenda-like view :: ~org-ql-search~ (command), and ~org-ql-agenda~ (macro) ++ Showing an agenda-like view :: ~org-ql-search~ (command), ~org-ql-block~ (agenda function), and ~org-ql-agenda~ (macro) + Returning a list of matches or acting on them :: ~org-ql~ (macro), ~org-ql-select~ (function), and ~org-ql-query~ (function) Feedback on these APIs is welcome. Eventually, after being tested and polished, they will be considered stable. @@ -141,6 +141,30 @@ Arguments are listed next to predicate names, where applicable. *** Agenda-like views +**** 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: + +#+BEGIN_SRC elisp + (setq org-agenda-custom-commands + '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" + ((org-ql-block '(and (todo "SOMEDAY") + (tags "Emacs") + (priority "A"))) + (agenda))))) +#+END_SRC + +Which would be equivalent to a ~tags-todo~ search like this: + +#+BEGIN_SRC elisp + (setq org-agenda-custom-commands + '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" + ((tags-todo "PRIORITY=\"A\"+Emacs/!SOMEDAY") + (agenda))))) +#+END_SRC + +However, the ~org-ql-block~ version runs in about 1/5th the time. + **** Macro: ~org-ql-agenda~ This macro is like ~org-ql~, but it presents matching entries in an Agenda-like view. It's compatible with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]], which provides grouping. For example: @@ -314,6 +338,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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 [[https://github.com/pestctrl/emacs-config/blob/84c557982a860e86d6f67976a82ea776a7bd2c7a/config-org-new.org#my-own-agenda-renderer][Benson Chu's config]].) *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 1bdcb6e..227ea7d 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -241,6 +241,33 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (org-agenda-finalize) (goto-char (point-min))))) +(defun org-ql-agenda-block (query) + "Insert items for QUERY into current buffer. +QUERY should be an `org-ql' query form. Like other agenda block +commands, it searches files returned by function +`org-agenda-files'. Intended to be used as a user-defined +function in `org-agenda-custom-commands'. QUERY corresponds to +the `match' item in the custom command form." + (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 (org-ql-agenda--header-line-format from query)) + (insert (org-add-props (org-ql-agenda--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-agenda--format-element) + org-agenda-finalize-entries + insert))) + +(defalias 'org-ql-block 'org-ql-agenda-block) + (defun org-ql-agenda--header-line-format (buffers-files query) "Return header-line-format for BUFFERS-FILES and QUERY." (let* ((query-formatted (format "%S" query)) From 43545482a4121fa564caaea00cbdffcddd22cfc5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 09:44:02 -0500 Subject: [PATCH 239/970] Docs: Add example --- README.org | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.org b/README.org index cc371be..946ed9c 100644 --- a/README.org +++ b/README.org @@ -52,6 +52,15 @@ More examples are available in [[examples.org]]. (and (property "genre" "classical") (property "composer" "Chopin") (not (property "key")))) + + ;; Define a custom Org Agenda command which inserts an `org-ql-block' + ;; block before the regular agenda: + (setq org-agenda-custom-commands + '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" + ((org-ql-block '(and (todo "SOMEDAY") + (tags "Emacs") + (priority "A"))) + (agenda))))) #+END_SRC * Usage From 7829238988023c7260072d68d07f3bcf6341d242 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 10:36:57 -0500 Subject: [PATCH 240/970] Add: (org-ql-agenda--agenda) Optionally specify entries directly Should probably refactor this a bit more, but this is useful now. --- README.org | 1 + org-ql-agenda.el | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index 946ed9c..83a2fa7 100644 --- a/README.org +++ b/README.org @@ -348,6 +348,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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 [[https://github.com/pestctrl/emacs-config/blob/84c557982a860e86d6f67976a82ea776a7bd2c7a/config-org-new.org#my-own-agenda-renderer][Benson Chu's config]].) ++ Function ~org-ql-agenda--agenda~ optionally takes a list of entries as an argument. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 227ea7d..73e734b 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -201,23 +201,25 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-ql-agenda--agenda (buffers-files query &key sort buffer narrow super-groups) +(cl-defun org-ql-agenda--agenda (buffers-files query &key entries sort buffer narrow super-groups) "FIXME: Docstring" (declare (indent defun)) (when (and super-groups (not org-super-agenda-mode)) (user-error "`org-super-agenda-mode' must be activated to use grouping")) (let* ((org-super-agenda-groups super-groups) - (entries (--> (org-ql-select buffers-files - query - :sort sort - :narrow narrow - :action (lambda () - (->> (org-element-headline-parser (line-end-position)) - org-ql--add-markers))) - (mapcar #'org-ql-agenda--format-element it) - (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) - (t it)) - (s-join "\n" it))) + (entries (or entries + (--> (org-ql-select buffers-files + query + :sort sort + :narrow narrow + :action (lambda () + (->> (org-element-headline-parser (line-end-position)) + org-ql--add-markers)))))) + (string (--> entries + (mapcar #'org-ql-agenda--format-element it) + (cond ((bound-and-true-p org-super-agenda-mode) (org-super-agenda--group-items it)) + (t it)) + (s-join "\n" it))) (buffer (cl-etypecase buffer (string (org-ql-agenda--buffer buffer)) (null (org-ql-agenda--buffer buffer)) @@ -236,7 +238,7 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (setq-local header-line-format (org-ql-agenda--header-line-format buffers-files query)) ;; Clear buffer, insert entries, etc. (erase-buffer) - (insert entries) + (insert string) (pop-to-buffer (current-buffer)) (org-agenda-finalize) (goto-char (point-min))))) From 4970d441cc2df69092fd3e87f14d3bcd17754e9b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 10:52:33 -0500 Subject: [PATCH 241/970] Change: (org-ql-agenda--format-element) Return empty string if nil This allows mapping the function across elements which may be nil, helping to separate items in agenda views by inserting nil between them. --- org-ql-agenda.el | 134 ++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 73e734b..5423887 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -326,72 +326,76 @@ dates in the past, and negative for dates in the future." ;; This essentially needs to do what `org-agenda-format-item' does, ;; which is a lot. We are a long way from that, but it's a start. "Return ELEMENT as a string with text-properties set by its property list. -Its property list should be the second item in the list, as returned by `org-element-parse-buffer'." - (let* ((properties (cadr element)) - ;; Remove the :parent property, which so bloats the size of - ;; the properties list that it makes it essentially - ;; impossible to debug, because Emacs takes approximately - ;; forever to show it in the minibuffer or with - ;; `describe-text-properties'. FIXME: Shouldn't be necessary - ;; anymore since we're not parsing the whole buffer. +Its property list should be the second item in the list, as +returned by `org-element-parse-buffer'. If ELEMENT is nil, +return an empty string." + (if (not element) + "" + (let* ((properties (cadr element)) + ;; Remove the :parent property, which so bloats the size of + ;; the properties list that it makes it essentially + ;; impossible to debug, because Emacs takes approximately + ;; forever to show it in the minibuffer or with + ;; `describe-text-properties'. FIXME: Shouldn't be necessary + ;; anymore since we're not parsing the whole buffer. - ;; Also, remove ":" from key symbols. FIXME: It would be - ;; better to avoid this somehow. At least, we should use a - ;; function to convert plists to alists, if possible. - (properties (cl-loop for (key val) on properties by #'cddr - for symbol = (intern (cl-subseq (symbol-name key) 1)) - unless (member symbol '(parent)) - append (list symbol val))) - ;; TODO: --add-faces is used to add the :relative-due-date property, but that fact is - ;; hidden by doing it through --add-faces (which calls --add-scheduled-face and - ;; --add-deadline-face), and doing it in this form that gets the title hides it even more. - ;; Adding the relative due date property should probably be done explicitly and separately - ;; (which would also make it easier to do it independently of faces, etc). - (title (--> (org-ql-agenda--add-faces element) - (org-element-property :raw-value it) - (org-link-display-format it))) - (todo-keyword (-some--> (org-element-property :todo-keyword element) - (org-ql-agenda--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...) - (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))) - ;; No marker found - (warn "No marker found for item: %s" title) - (org-element-property :tags element)) - (org-element-property :tags element))) - (tag-string (-some--> tag-list - (s-join ":" it) - (s-wrap it ":") - (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-agenda--add-priority-face))) - (habit-property (org-with-point-at (org-element-property :begin element) - (when (org-is-habit-p) - (org-habit-parse-todo)))) - (due-string (pcase (org-element-property :relative-due-date element) - ('nil "") - (string (format " %s " (org-add-props string nil 'face 'underline))))) - (string (s-join " " (-non-nil (list todo-keyword priority-string title due-string tag-string))))) - (remove-list-of-text-properties 0 (length string) '(line-prefix) string) - ;; Add all the necessary properties and faces to the whole string - (--> string - ;; FIXME: Use proper prefix - (concat " " it) - (org-add-props it properties - 'todo-state todo-keyword - 'tags tag-list - 'org-habit-p habit-property)))) + ;; Also, remove ":" from key symbols. FIXME: It would be + ;; better to avoid this somehow. At least, we should use a + ;; function to convert plists to alists, if possible. + (properties (cl-loop for (key val) on properties by #'cddr + for symbol = (intern (cl-subseq (symbol-name key) 1)) + unless (member symbol '(parent)) + append (list symbol val))) + ;; TODO: --add-faces is used to add the :relative-due-date property, but that fact is + ;; hidden by doing it through --add-faces (which calls --add-scheduled-face and + ;; --add-deadline-face), and doing it in this form that gets the title hides it even more. + ;; Adding the relative due date property should probably be done explicitly and separately + ;; (which would also make it easier to do it independently of faces, etc). + (title (--> (org-ql-agenda--add-faces element) + (org-element-property :raw-value it) + (org-link-display-format it))) + (todo-keyword (-some--> (org-element-property :todo-keyword element) + (org-ql-agenda--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...) + (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))) + ;; No marker found + (warn "No marker found for item: %s" title) + (org-element-property :tags element)) + (org-element-property :tags element))) + (tag-string (-some--> tag-list + (s-join ":" it) + (s-wrap it ":") + (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-agenda--add-priority-face))) + (habit-property (org-with-point-at (org-element-property :begin element) + (when (org-is-habit-p) + (org-habit-parse-todo)))) + (due-string (pcase (org-element-property :relative-due-date element) + ('nil "") + (string (format " %s " (org-add-props string nil 'face 'underline))))) + (string (s-join " " (-non-nil (list todo-keyword priority-string title due-string tag-string))))) + (remove-list-of-text-properties 0 (length string) '(line-prefix) string) + ;; Add all the necessary properties and faces to the whole string + (--> string + ;; FIXME: Use proper prefix + (concat " " it) + (org-add-props it properties + 'todo-state todo-keyword + 'tags tag-list + 'org-habit-p habit-property))))) (defun org-ql-agenda--add-faces (element) "Return ELEMENT with deadline and scheduled faces added." From d9b7647f5bc16973d48efada987669c52e7c7221 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 15:25:07 -0500 Subject: [PATCH 242/970] Meta: Add .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e5e85fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.elc +.#* +/scratch.el +.cask From 2dbe40d9ead5d3d6038ca5898431eae190b50144 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 15:28:36 -0500 Subject: [PATCH 243/970] Fix: (org-ql-select) Accept special forms and macros in action --- org-ql.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 3c323d2..e26ca94 100644 --- a/org-ql.el +++ b/org-ql.el @@ -165,7 +165,9 @@ non-nil." `(lambda (&rest _ignore) (org-element-headline-parser (line-end-position))))) ((pred functionp) action) - ((and (pred listp) (guard (functionp (car action)))) + ((and (pred listp) (guard (or (special-form-p (car action)) + (macrop (car action)) + (functionp (car action))))) (byte-compile `(lambda (&rest _ignore) ,action))) From 00d9bbd85beb5a213176b991164cf188ed828a79 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 15:29:53 -0500 Subject: [PATCH 244/970] Tests: Add makem.sh, update Makefile --- Makefile | 25 ++- makem.sh | 539 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 561 insertions(+), 3 deletions(-) create mode 100755 makem.sh diff --git a/Makefile b/Makefile index d5edecf..4883294 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,23 @@ -.PHONY: test +# * Verbosity -test: - cask exec buttercup -L . +# Since the "-v" in "make -v" gets intercepted by Make itself, we have +# to use a variable. + +verbose = $(v) + +ifneq (,$(findstring vv,$(verbose))) + VERBOSE = "-vv" +else ifneq (,$(findstring v,$(verbose))) + VERBOSE = "-v" +endif + +# * Rules + +# Unless/until I add Cask support to makem.sh, I'm keeping this, +# because Cask lets me run the tests with a different version of Org +# than I have installed personally. +cask: + @cask exec buttercup -L . + +%: + @./makem.sh $(VERBOSE) $(@) diff --git a/makem.sh b/makem.sh new file mode 100755 index 0000000..909d9eb --- /dev/null +++ b/makem.sh @@ -0,0 +1,539 @@ +#!/bin/bash + +# * makem.sh --- Script to aid building and testing Emacs Lisp packages + +# * Commentary: + + +# * 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 . + +# * Safety + +# 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 + +# These functions return a path to an elisp file which can be loaded +# by Emacs on the command line with -l or --load. + +function elisp-buttercup-file { + # The function buttercup-run, which is called by buttercup-run-discover, + # signals an error if it can't find any Buttercup test suites. We don't + # want that to be an error, so we define advice which ignores that error. + local file=$(mktemp) + cat >$file <$file <$file <$output_file + + exit=$? + [[ $exit != 0 ]] && debug "Emacs exited non-zero: $exit" + if [[ $verbose -gt 1 || $exit != 0 ]] + then + cat $output_file + fi + rm -f $output_file + + return $exit +} + +# ** Compilation + +function batch-byte-compile { + debug "batch-byte-compile: ERROR-ON-WARN:$compile_error_on_warn FILES:$@" + + [[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq byte-compile-error-on-warn t)") + + run_emacs \ + "${error_on_warn[@]}" \ + --funcall batch-byte-compile \ + "$@" +} + +# ** Files + +function project-elisp-files { + # Echo list of Elisp files in project. + git ls-files 2>/dev/null | egrep "\.el$" | exclude-files +} + +function project-source-files { + # Echo list of Elisp files that are not tests. + project-elisp-files | egrep -v '^tests?/test-?' +} + +function project-test-files { + # Echo list of Elisp test files. + project-elisp-files | egrep '^tests?/test-?' +} + +function exclude-files { + # Filter out paths (STDIN) which should be excluded by default. + egrep -v "(/\.cask/|-autoloads.el)" +} + +function load-files-args { + # For file in $@, echo "--load $file". + for file in "$@" + do + printf -- '--load %q ' "$file" + done +} + +function files_args { + # For file in STDIN, echo "$file". + while read file + do + printf -- '%q ' "$file" + done +} + +# ** Utility + +function cleanup { + # Remove temporary paths (${temp_paths[@]}). + + for path in "${temp_paths[@]}" + do + if [[ $debug ]] + then + debug "Debugging enabled: not deleting temporary path: $path" + elif [[ -r $path ]] + then + rm -rf "$path" + else + debug "Temporary path doesn't exist, not deleting: $path" + fi + done +} + +function echo_color { + # This allows bold, italic, etc. without needing a function for + # each variation. + if [[ $color ]] + then + local color_code="COLOR_$1" + shift + + echo -e "${!color_code}${@}${COLOR_off}" + else + echo "$@" + fi +} +function debug { + if [[ $debug ]] + then + function debug { + echo_color yellow "DEBUG ($(ts)): $@" >&2 + } + debug "$@" + else + function debug { + true + } + fi +} +function error { + echo_color red "ERROR ($(ts)): $@" >&2 + ((errors++)) +} +function die { + error "$@" + exit $errors +} +function log { + echo "LOG ($(ts)): $@" >&2 +} +function log_color { + local color=$1 + shift + echo_color $color "LOG ($(ts)): $@" >&2 +} +function success { + if [[ $verbose -ge 2 ]] + then + log_color green "$@" >&2 + fi +} +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 + + shift + log_color $color "$@" >&2 + fi +} + +function ts { + date "+%Y-%m-%d %H:%M:%S" +} + +function usage { + cat </dev/null | grep "$rule is a function" &>/dev/null + then + $rule + elif [[ $rule = test ]] + then + # Allow the "tests" rule to be called as "test". Since "test" + # is a shell builtin, this workaround is required. + tests + else + error "Invalid rule: $rule" + fi +done + +if [[ $errors -gt 0 ]] +then + log_color red "Finished with $errors errors." +else + success "Finished without errors." +fi + +exit $errors From cc92fccb7fcd45b7243eda73e80ed26995a93b8b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 8 Aug 2019 17:07:25 -0500 Subject: [PATCH 245/970] Test: Simplify with org-ql-expect macro --- tests/test-org-ql.el | 418 ++++++++++++++++++------------------------- 1 file changed, 172 insertions(+), 246 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 0925ba6..5995e1a 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -91,6 +91,16 @@ Based on Buttercup macro `it'." ,@body)))) `(buttercup-xit ,description))) +(defmacro org-ql-expect (ql-args results) + "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 test-buffer + ,@ql-args + :action (org-ql-test-org-get-heading)) + :to-equal ,results)) + ;;;; Tests (describe "org-ql" @@ -162,313 +172,229 @@ Based on Buttercup macro `it'." ;; TODO: Other predicates. (describe "(category)" + (org-ql-it "without arguments" (expect (length (org-ql test-buffer - (category) - :action (org-ql-test-org-get-heading))) + (category))) :to-equal num-headings)) + (org-ql-it "with a category" - (expect (org-ql test-buffer - (category "ambition") - :action (org-ql-test-org-get-heading)) - :to-equal '("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 "(clocked)" + (org-ql-it "without arguments" - (expect (org-ql test-buffer - (clocked) - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language"))) + (org-ql-expect ((clocked)) + '("Learn universal sign language"))) + (org-ql-it ":from a timestamp" - (expect (org-ql test-buffer - (clocked :from "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (clocked :from "2017-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal 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 ":to a timestamp" - (expect (org-ql test-buffer - (clocked :to "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (clocked :to "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal 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 ":on a date" - (expect (org-ql test-buffer - (clocked :on "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (clocked :on "2018-12-02") - :action (org-ql-test-org-get-heading)) - :to-equal 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 "within a range (:from and :to)" - (expect (org-ql test-buffer - (clocked :from "2017-07-04" :to "2018-12-11") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (clocked :from "2017-07-06" :to "2018-12-11") - :action (org-ql-test-org-get-heading)) - :to-equal nil) - (expect (org-ql test-buffer - (clocked :from "2017-07-01" :to "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal 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" - (expect (org-ql test-buffer - (closed) - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language"))) + (org-ql-expect ((closed)) + '("Learn universal sign language"))) + (org-ql-it "=" - (expect (org-ql test-buffer - (closed = "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed = "2019-06-09") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((closed = "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((closed = "2019-06-09")) + nil)) + (org-ql-it "<" ;; TODO: Figure out why these tests take about 8 times longer than the other comparators in the (closed) tests. - (expect (org-ql test-buffer - (closed < "2019-06-10") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed < "2017-06-10") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((closed < "2019-06-10")) + '("Learn universal sign language")) + (org-ql-expect ((closed < "2017-06-10")) + nil)) + (org-ql-it ">" - (expect (org-ql test-buffer - (closed > "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed > "2019-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((closed > "2017-07-04")) + '("Learn universal sign language")) + (org-ql-expect ((closed > "2019-07-05")) + nil)) + (org-ql-it ">=" - (expect (org-ql test-buffer - (closed >= "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed >= "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed >= "2017-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((closed >= "2017-07-04")) + '("Learn universal sign language")) + (org-ql-expect ((closed >= "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((closed >= "2017-07-06")) + nil)) + (org-ql-it "<=" - (expect (org-ql test-buffer - (closed <= "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal nil) - (expect (org-ql test-buffer - (closed <= "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")) - (expect (org-ql test-buffer - (closed <= "2017-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language")))) + (org-ql-expect ((closed <= "2017-07-04")) + nil) + (org-ql-expect ((closed <= "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((closed <= "2017-07-06")) + '("Learn universal sign language")))) (describe "(deadline)" + (org-ql-it "without arguments" - (expect (org-ql test-buffer - (deadline) - :action (org-ql-test-org-get-heading)) - :to-equal '("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 "=" - (expect (org-ql test-buffer - (deadline = "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("/r/emacs")) - (expect (org-ql test-buffer - (deadline = "2019-06-09") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((deadline = "2017-07-05")) + '("/r/emacs")) + (org-ql-expect ((deadline = "2019-06-09")) + nil)) + (org-ql-it "<" - (expect (org-ql test-buffer - (deadline < "2019-06-10") - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (expect (org-ql test-buffer - (deadline < "2017-06-10") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((deadline < "2019-06-10")) + '("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 < "2017-06-10")) + nil)) + (org-ql-it ">" ;; TODO: Figure out why these tests take much longer than e.g. the (deadline <) tests. - (expect (org-ql test-buffer - (deadline > "2017-07-04 00:00") - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (expect (org-ql test-buffer - (deadline > "2019-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((deadline > "2017-07-04 00:00")) + '("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 > "2019-07-05")) + nil)) + (org-ql-it ">=" - (expect (org-ql test-buffer - (deadline >= "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (expect (org-ql test-buffer - (deadline >= "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease" "/r/emacs")) - (expect (org-ql test-buffer - (deadline >= "2017-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Visit Mars" "Visit the moon" "Renew membership in supervillain club" "Internet" "Spaceship lease")) - (expect (org-ql test-buffer - (deadline >= "2018-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((deadline >= "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 >= "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 >= "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 >= "2018-07-06")) + nil)) + (org-ql-it "<=" - (expect (org-ql test-buffer - (deadline <= "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal nil) - (expect (org-ql test-buffer - (deadline <= "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("/r/emacs")) - (expect (org-ql test-buffer - (deadline <= "2018-07-06") - :action (org-ql-test-org-get-heading)) - :to-equal '("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 <= "2017-07-04")) + nil) + (org-ql-expect ((deadline <= "2017-07-05")) + '("/r/emacs")) + (org-ql-expect ((deadline <= "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-it "(done)" - (expect (org-ql test-buffer - (done) - :action (org-ql-test-org-get-heading)) - :to-equal '("Learn universal sign language"))) + (org-ql-expect ((done)) + '("Learn universal sign language"))) (describe "(regexp)" + (org-ql-it "with 1 argument" - (expect (org-ql test-buffer - (regexp "Take over") - :sort todo - :action (org-ql-test-org-get-heading)) :to-equal '("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" - (expect (org-ql test-buffer - (regexp "Take over" "pizza") - :sort todo - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut"))) + (org-ql-expect ((regexp "Take over" "pizza") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut"))) + (org-ql-it "with a plain string" - (expect (org-ql test-buffer - "Take over" - :sort todo - :action (org-ql-test-org-get-heading)) - :to-equal '("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" - (expect (org-ql test-buffer - (or "Take over" "pizza") - :sort todo - :action (org-ql-test-org-get-heading)) - :to-equal '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) + (org-ql-expect ((or "Take over" "pizza") + :sort todo) + '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "Get haircut")))) (describe "(todo)" + (org-ql-it "without arguments" ;; FIXME: This returns an item that is done, which is incorrect. - (expect (org-ql test-buffer - (todo) - :sort todo - :action (org-ql-test-org-get-heading)) :to-equal '("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 ((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" "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-it "with 1 argument" ;; FIXME: Figure out why this takes >10x longer than the other (todo) ;; tests, according to Buttercup. Might just be GC, though. - (expect (org-ql test-buffer - (todo "WAITING") - :sort todo - :action (org-ql-test-org-get-heading)) :to-equal '("Visit the moon"))) + (org-ql-expect ((todo "WAITING") + :sort todo) + '("Visit the moon"))) + (org-ql-it "with 2 arguments" - (expect (org-ql test-buffer - (todo "WAITING" "SOMEDAY") - :sort todo - :action (org-ql-test-org-get-heading)) :to-equal '("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" - (expect (org-ql test-buffer - (tags) - :action (org-ql-test-org-get-heading)) - :to-equal '("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")) - (expect (org-ql test-buffer - (not (tags)) - :action (org-ql-test-org-get-heading)) - :to-equal '("Test data" "Recurring" "Sunrise/sunset" "Ideas" "Code" "Agenda examining" "Agenda censoring" "Auto grouping" "Auto categories" "Date" "Effort" "Misc" "let-plist" "Profiling"))) + (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"))) + (org-ql-it "with a tag" - (expect (org-ql test-buffer - (tags "Emacs") - :action (org-ql-test-org-get-heading)) - :to-equal '("/r/emacs" "Rewrite Emacs in Common Lisp")) - (expect (org-ql test-buffer - (not (tags "Emacs")) - :action (org-ql-test-org-get-heading)) - :to-equal '("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"))) + (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"))) + (org-ql-it "with 2 tags" - (expect (org-ql test-buffer - (tags "Emacs" "space") - :action (org-ql-test-org-get-heading)) - :to-equal '("Visit Mars" "Visit the moon" "/r/emacs" "Rewrite Emacs in Common Lisp")) - (expect (org-ql test-buffer - (not (tags "Emacs" "space")) - :action (org-ql-test-org-get-heading)) - :to-equal '("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")))) + (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")))) (describe "(ts)" + (org-ql-it "without arguments" - (expect (org-ql test-buffer - (ts) - :action (org-ql-test-org-get-heading)) - :to-equal '("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"))) + (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"))) + (org-ql-it ":from a timestamp" ;; TODO: Figure out why these take longer than the other (ts) tests. - (expect (org-ql test-buffer - (ts :from "2017-01-01") - :action (org-ql-test-org-get-heading)) - :to-equal '("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")) - (expect (org-ql test-buffer - (ts :from "2019-06-08") - :action (org-ql-test-org-get-heading)) - :to-equal nil)) + (org-ql-expect ((ts :from "2017-01-01")) + '("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")) + (org-ql-expect ((ts :from "2019-06-08")) + nil)) + (org-ql-it ":to a timestamp" - (expect (org-ql test-buffer - (ts :to "2019-06-10") - :action (org-ql-test-org-get-heading)) - :to-equal '("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")) - (expect (org-ql test-buffer - (ts :to "2017-07-04") - :action (org-ql-test-org-get-heading)) - :to-equal '("Skype with president of Antarctica"))) + (org-ql-expect ((ts :to "2019-06-10")) + '("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")) + (org-ql-expect ((ts :to "2017-07-04")) + '("Skype with president of Antarctica"))) + (org-ql-it ":on a timestamp" - (expect (org-ql test-buffer - (ts :on "2017-07-05") - :action (org-ql-test-org-get-heading)) - :to-equal '("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")) - (expect (org-ql test-buffer - (ts :on "2019-06-09") - :action (org-ql-test-org-get-heading)) - :to-equal nil))) + (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")) + (org-ql-expect ((ts :on "2019-06-09")) + nil))) (describe "Compound queries" (org-ql-it "Tags and to-do" - (expect (org-ql test-buffer - (and (todo "SOMEDAY") - (tags "Emacs")) - :action (org-ql-test-org-get-heading)) - :to-equal '("Rewrite Emacs in Common Lisp")))))) + (org-ql-expect ((and (todo "SOMEDAY") + (tags "Emacs"))) + '("Rewrite Emacs in Common Lisp")))))) ;; Local Variables: ;; truncate-lines: t From b12d498cec69b141feae05ec1296a0f5da719ff0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 16:47:01 -0500 Subject: [PATCH 246/970] Tests: Update helper functions --- tests/test-org-ql.el | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 5995e1a..4e5a8cf 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -39,15 +39,21 @@ (if-let* ((sexp (elisp--preceding-sexp)) (correct-sexp-p (pcase (car sexp) ('org-ql 'org-ql) + ('org-ql-expect t) ('org-ql--query-preamble 'query-preamble) ('org-ql--pre-process-query t) (_ nil))) - (result (pcase (car sexp) - ('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))) + (result (pcase sexp + (`(org-ql-expect ,args) (org-ql-test--format-result--ql `(org-ql test-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))) (_ nil)))) - (insert " :to-equal " result) + (progn + (backward-char 1) + (insert "\n'" result)) (user-error "Point must be after an `org-ql' form"))) (defun org-ql-test--format-result--ql (sexp) @@ -67,10 +73,13 @@ "Show `org-ql-agenda' for `org-ql' form." (interactive) (if-let* ((sexp (elisp--preceding-sexp)) - (correct-sexp-p (eq (car sexp) 'org-ql))) - (progn - (setf (car sexp) 'org-ql-agenda) - (eval sexp)) + (sexp (pcase sexp + (`(org-ql . ,_) (setf (car sexp) 'org-ql-agenda)) + (`(org-ql-expect ,ql-args . ,_) (setf sexp `(org-ql-agenda test-buffer + ,@ql-args))) + (_ nil)))) + + (eval sexp) (user-error "Point must be after an `org-ql' form"))) ;;;; Macros From e7eb3b2031429a30371d17f34ade539b44e7cd5c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 16:47:56 -0500 Subject: [PATCH 247/970] Add: (property) Preambles --- notes.org | 46 ++++++++++++++++++++++++++++++++++++++++++-- org-ql.el | 23 ++++++++++++++++++++++ tests/test-org-ql.el | 14 ++++++++++++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/notes.org b/notes.org index 9694dd2..f7f2d75 100644 --- a/notes.org +++ b/notes.org @@ -416,11 +416,15 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled ** 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))) - ("no preamble" ((org-ql-use-preamble nil)))) + :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)))))) @@ -440,6 +444,44 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled | 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 | + *** =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. diff --git a/org-ql.el b/org-ql.el index e26ca94..58a3286 100644 --- a/org-ql.el +++ b/org-ql.el @@ -343,6 +343,29 @@ replace the clause with a preamble." (`(level ,num) (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) nil) + (`(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) ((and `(tags . ,tags) (guard (not org-use-tag-inheritance))) ;; When tag inheritance is disabled, we only consider direct tags, ;; so we can search directly to headings containing one of the tags. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 4e5a8cf..51761f1 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -311,6 +311,20 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((done)) '("Learn universal sign language"))) + (describe "(property)" + + ;; MAYBE: Add support for (property) without arguments. + ;; (org-ql-it "without arguments" + ;; (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-it "with a property and a value" + (org-ql-expect ((property "agenda-group" "plans")) + '("Take over the universe" "Write a symphony")))) + (describe "(regexp)" (org-ql-it "with 1 argument" From ed26effe1c40064941526e9f9a8e66ba3a8c8554 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:05:17 -0500 Subject: [PATCH 248/970] Add: (deadline) preamble --- notes.org | 26 ++++++++++++++++++++++++++ org-ql.el | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/notes.org b/notes.org index f7f2d75..7f834e0 100644 --- a/notes.org +++ b/notes.org @@ -430,6 +430,32 @@ Not sure if clearing the cache is necessary here, because it seemed to make near :action '(org-get-heading t t)))))) #+END_SRC +*** =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 | + *** =level= #+BEGIN_SRC elisp diff --git a/org-ql.el b/org-ql.el index 58a3286..0a9f431 100644 --- a/org-ql.el +++ b/org-ql.el @@ -316,6 +316,15 @@ replace the clause with a preamble." element) (pcase element (`(or _) element) + (`(deadline . ,_) + (setq org-ql-preamble + (rx-to-string `(seq bol (0+ (any " ")) "DEADLINE" ":" (1+ space) (1+ not-newline)) t)) + ;; Return element, because the predicate still needs testing. + element) + (`(deadline) + (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "DEADLINE" ":") t)) + ;; Return element, because the predicate still needs testing. + element) (`(regexp . ,regexps) (setq org-ql-preamble (rx-to-string `(or ,@regexps) t)) ;; Return nil, because we don't need to test the predicate. From cd4f3cc99b57eb54ab74b48e29e959d2f2cc0805 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:07:49 -0500 Subject: [PATCH 249/970] Add: (scheduled) preamble --- notes.org | 26 ++++++++++++++++++++++++++ org-ql.el | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/notes.org b/notes.org index 7f834e0..8397172 100644 --- a/notes.org +++ b/notes.org @@ -508,6 +508,32 @@ Not sure if clearing the cache is necessary here, because it seemed to make near | 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. diff --git a/org-ql.el b/org-ql.el index 0a9f431..0cdaa2c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -375,6 +375,15 @@ 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) + (`(scheduled . ,_) + (setq org-ql-preamble + (rx-to-string `(seq bol (0+ (any " ")) "SCHEDULED" ":" (1+ space) (1+ not-newline)) t)) + ;; Return element, because the predicate still needs testing. + element) + (`(scheduled) + (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "SCHEDULED" ":") t)) + ;; Return element, because the predicate still needs testing. + element) ((and `(tags . ,tags) (guard (not org-use-tag-inheritance))) ;; When tag inheritance is disabled, we only consider direct tags, ;; so we can search directly to headings containing one of the tags. From 13993f1394fa87466351af621eee0adc5f54dcf1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:10:03 -0500 Subject: [PATCH 250/970] Add: (closed) preamble --- notes.org | 26 ++++++++++++++++++++++++++ org-ql.el | 9 +++++++++ 2 files changed, 35 insertions(+) diff --git a/notes.org b/notes.org index 8397172..fff5876 100644 --- a/notes.org +++ b/notes.org @@ -430,6 +430,32 @@ Not sure if clearing the cache is necessary here, because it seemed to make near :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 diff --git a/org-ql.el b/org-ql.el index 0cdaa2c..b66f0a3 100644 --- a/org-ql.el +++ b/org-ql.el @@ -316,6 +316,15 @@ replace the clause with a preamble." element) (pcase element (`(or _) element) + (`(closed . ,_) + (setq org-ql-preamble + (rx-to-string `(seq bol (0+ (any " ")) "CLOSED" ":" (1+ space) (1+ not-newline)) t)) + ;; Return element, because the predicate still needs testing. + element) + (`(closed) + (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "CLOSED" ":") t)) + ;; Return element, because the predicate still needs testing. + element) (`(deadline . ,_) (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "DEADLINE" ":" (1+ space) (1+ not-newline)) t)) From 867bf4edccb097c4da583a26bfba2b32cb21c26b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:12:27 -0500 Subject: [PATCH 251/970] Docs: Add note about (property) inheritance --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 83a2fa7..f6b3193 100644 --- a/README.org +++ b/README.org @@ -134,7 +134,7 @@ Arguments are listed next to predicate names, where applicable. + ~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 ~>=~. + ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~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. -+ ~property (property &optional value)~ :: Return non-nil if current entry has ~PROPERTY~ (a string), and optionally ~VALUE~ (a string). ++ ~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 (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). + ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). From 1c5bf06804f232e195419ac6992f3e2d4b7ac950 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:18:56 -0500 Subject: [PATCH 252/970] Tests: Add (habit) --- 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 51761f1..4875897 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -311,6 +311,10 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((done)) '("Learn universal sign language"))) + (org-ql-it "(habit)" + (org-ql-expect ((habit)) + '("Practice leaping tall buildings in a single bound"))) + (describe "(property)" ;; MAYBE: Add support for (property) without arguments. From 2cdc2106458fd99dd4da82841e1ea49e86ffaaf5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 9 Aug 2019 17:19:07 -0500 Subject: [PATCH 253/970] Add: (habit) preamble --- notes.org | 14 ++++++++++++++ org-ql.el | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/notes.org b/notes.org index fff5876..e224aca 100644 --- a/notes.org +++ b/notes.org @@ -482,6 +482,20 @@ Not sure if clearing the cache is necessary here, because it seemed to make near | 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 diff --git a/org-ql.el b/org-ql.el index b66f0a3..24d6d2c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -348,6 +348,10 @@ replace the clause with a preamble." t)) ;; Return nil, don't test the predicate. nil) + (`(habit) + (setq org-ql-preamble (rx-to-string `(seq bol (0+ space) ":STYLE:" (1+ space) + "habit" (0+ space) eol))) + nil) (`(level ,comparator-or-num ,num) (let ((repeat (pcase comparator-or-num ('< `(repeat 1 ,(1- num) "*")) From bd3ab6fb02c4c08c99690a3e308c8a2f642898a5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 10 Aug 2019 06:16:59 -0500 Subject: [PATCH 254/970] Notes: Add idea --- notes.org | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/notes.org b/notes.org index e224aca..6164ac4 100644 --- a/notes.org +++ b/notes.org @@ -4,6 +4,49 @@ ** TODO Update commentary +** TODO ~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 [#B] Implied string literal regexp selector As mentioned [[https://www.reddit.com/r/emacs/comments/c8e0zp/my_gnu_hyperbole_vision_quest_odyssey_two/esmtqow/][here]]: From ab0df68aae4f7558d47276f9758e9a7681b4d649 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 10 Aug 2019 10:18:03 -0500 Subject: [PATCH 255/970] Add: (org-ql-query) narrow, order-by --- README.org | 7 ++++++- org-ql.el | 13 ++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index f6b3193..9bcb3f5 100644 --- a/README.org +++ b/README.org @@ -286,7 +286,7 @@ Examples: **** Function: ~org-ql-query~ -/Arguments:/ ~(&key (select 'element-with-markers) from where)~ +/Arguments:/ ~(&key (select 'element-with-markers) from where order-by narrow)~ Like ~org-ql-select~, but arguments are named more like a ~SQL~ query. @@ -296,6 +296,11 @@ Like ~org-ql-select~, but arguments are named more like a ~SQL~ query. ~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: #+BEGIN_SRC elisp diff --git a/org-ql.el b/org-ql.el index 24d6d2c..dcc6321 100644 --- a/org-ql.el +++ b/org-ql.el @@ -196,7 +196,7 @@ non-nil." ((pred functionp) (sort items sort)) (_ (user-error "SORT must be either nil, or one or a list of the defined sorting methods (see documentation)"))))) -(cl-defun org-ql-query (&key (select 'element-with-markers) from where) +(cl-defun org-ql-query (&key (select 'element-with-markers) from where narrow order-by) "Like `org-ql-select', but arguments are named more like a SQL query. SELECT corresponds to the `org-ql-select' argument ACTION. It is @@ -219,10 +219,17 @@ FROM corresponds to the `org-ql-select' argument BUFFERS-OR-FILES. It may be one or a list of file paths and/or buffers. WHERE corresponds to the `org-ql-select' argument QUERY. It -should be an `org-ql' query sexp." +should be an `org-ql' query sexp. + +ORDER-BY corresponds to the `org-ql-select' argument SORT, which +see. + +NARROW corresponds to the `org-ql-select' argument NARROW." (declare (indent defun)) (org-ql-select from where - :action select)) + :action select + :narrow narrow + :sort sort)) (defun org-ql--pre-process-query (query) "Return QUERY having been pre-processed. From 6abb2ae8c0c6876c5590ef003ef71c53c9dc3015 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 10 Aug 2019 10:18:29 -0500 Subject: [PATCH 256/970] Docs: Improve examples --- README.org | 58 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/README.org b/README.org index 9bcb3f5..48be5ed 100644 --- a/README.org +++ b/README.org @@ -25,36 +25,48 @@ More examples are available in [[examples.org]]. #+BEGIN_SRC elisp - ;; Return a list of Org entry elements in the file "~/org/main.org" which have the SOMEDAY - ;; to-do keyword, are tagged "Emacs", and have priority B or higher. + ;; Return a list of Org entry elements in the file "~/org/main.org" + ;; which have the SOMEDAY to-do keyword, are tagged "Emacs", and have + ;; priority B or higher. (org-ql "~/org/main.org" (and (todo "SOMEDAY") (tags "Emacs") - (priority >= "B"))) ;=> ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) + (priority >= "B"))) + ;;=> ((headline (:raw-value "org-board" :begin 1220270 :end 1220403 ...)) ...) - ;; Return a list of bills coming due, searching all Org Agenda files, sorted by deadline. Deadlines - ;; are compared with configured Org warning days, which is implied by the plain `<=' in the - ;; `deadline' matcher. - (org-ql (org-agenda-files) - (and (not (done)) - (tags "bills") - (deadline <=)) - :sort deadline) + ;; Set the tag "Emacs" on every entry in the inbox file that mentions + ;; "Emacs". `org-ql-select' works like `org-ql' but is a function + ;; rather than a macro. The bare-string query "Emacs" is equivalent + ;; to (regexp "Emacs"). + (org-ql-select "~/org/inbox.org" + "Emacs" + :action '(org-toggle-tag "Emacs" 'on)) - ;; Set the tag "Emacs" on every entry in the inbox file that mentions "Emacs". - (org-ql "~/org/inbox.org" - (regexp "Emacs") - :action (org-toggle-tag "Emacs" 'on)) + ;; Return a list of bills coming due, searching all Org Agenda files, + ;; sorted by deadline. Deadlines are compared with + ;; `org-deadline-warning-days', which is implied by the plain `<=' in + ;; the `deadline' predicate. `org-ql-query' works like `org-ql-select' + ;; but offers arguments named like SQL queries. + (org-ql-query + :select #'org-get-heading + :from (org-agenda-files) + :where '(and (not (done)) + (tags "bills") + (deadline <=)) + :order-by 'deadline) + ;;=> ("TODO Electric bill" "TODO Water bill") - ;; If you kept a database of music in an Org file, you might run a query like this to find tracks - ;; composed by Chopin that do not have their key recorded in the database: - (org-ql "~/org/music.org" - (and (property "genre" "classical") - (property "composer" "Chopin") - (not (property "key")))) + ;; If you kept a database of music in an Org file, you could run a + ;; query like this to find tracks composed by Chopin that do not have + ;; their key recorded in the database. `org-ql-search' works like + ;; `org-ql-select' and displays results in an agenda-like buffer: + (org-ql-search "~/org/music.org" + '(and (property "genre" "classical") + (property "composer" "Chopin") + (not (property "key")))) - ;; Define a custom Org Agenda command which inserts an `org-ql-block' - ;; block before the regular agenda: + ;; Integrate `org-ql' into a custom Org Agenda command which inserts + ;; an `org-ql' block before the regular agenda: (setq org-agenda-custom-commands '(("ces" "Custom: Agenda and Emacs SOMEDAY [#A] items" ((org-ql-block '(and (todo "SOMEDAY") From c615fbd73fe843e1fde516b49308e973a283b166 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sat, 10 Aug 2019 10:21:37 -0500 Subject: [PATCH 257/970] Docs: -query args --- README.org | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.org b/README.org index 48be5ed..47a20a5 100644 --- a/README.org +++ b/README.org @@ -302,16 +302,11 @@ Examples: 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~. ++ ~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: From a77e60640b5c4fdcebb71bf9787e87da9c7f538a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 10:41:48 -0500 Subject: [PATCH 258/970] Fix: (org-ql-query) Argument Oops. --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index dcc6321..616908c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -229,7 +229,7 @@ NARROW corresponds to the `org-ql-select' argument NARROW." (org-ql-select from where :action select :narrow narrow - :sort sort)) + :sort order-by)) (defun org-ql--pre-process-query (query) "Return QUERY having been pre-processed. From 1ca5930b2fb4941d210626b882dd4640b7583616 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 11:02:46 -0500 Subject: [PATCH 259/970] Tidy: (org-ql-query) Indentation --- org-ql.el | 1 - 1 file changed, 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 616908c..7da1473 100644 --- a/org-ql.el +++ b/org-ql.el @@ -225,7 +225,6 @@ ORDER-BY corresponds to the `org-ql-select' argument SORT, which see. NARROW corresponds to the `org-ql-select' argument NARROW." - (declare (indent defun)) (org-ql-select from where :action select :narrow narrow From b5f9087e586361baa3f4bd761c4286d50dd66a34 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 11:34:52 -0500 Subject: [PATCH 260/970] Tests: Update makem.sh --- makem.sh | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/makem.sh b/makem.sh index 909d9eb..07b8308 100755 --- a/makem.sh +++ b/makem.sh @@ -147,11 +147,20 @@ EOF # ** Emacs function run_emacs { - debug "run_emacs: emacs -Q --batch -L \"$load_path\" --load=$package_initialize_file $@" + debug "run_emacs: emacs -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) + fi output_file=$(mktemp) - emacs -Q --batch -L "$load_path" \ + emacs -Q --batch \ --load=$package_initialize_file \ + -L "$load_path" \ "$@" \ &>$output_file @@ -239,11 +248,11 @@ function cleanup { function echo_color { # This allows bold, italic, etc. without needing a function for # each variation. + local color_code="COLOR_$1" + shift + if [[ $color ]] then - local color_code="COLOR_$1" - shift - echo -e "${!color_code}${@}${COLOR_off}" else echo "$@" @@ -322,6 +331,8 @@ Options: -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. --no-color Disable color output. @@ -462,7 +473,7 @@ COLOR_white='\e[0;37m' # * Args -args=$(getopt -n "$0" -o dhvf:C -l debug,help,verbose,file:,no-color,no-compile -- "$@") || { usage; exit 1; } +args=$(getopt -n "$0" -o dhvf:C -l debug,debug-load-path,help,verbose,file:,no-color,no-compile -- "$@") || { usage; exit 1; } eval set -- "$args" while true @@ -472,6 +483,9 @@ do debug=true verbose=2 ;; + --debug-load-path) + debug_load_path=true + ;; -h|--help) usage exit From 913292787b938ca699a657a825916d343a3ba07b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 11:36:37 -0500 Subject: [PATCH 261/970] Tests: Query functions/macros Test a few basic forms of these to ensure, e.g. that arguments don't get broken. --- tests/test-org-ql.el | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 4875897..287c7bd 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -131,6 +131,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 "Query functions/macros" + + (it "org-ql" + (expect (length (org-ql test-buffer + (category) + :sort deadline)) + :to-equal num-headings)) + (it "org-ql-select" + (expect (length (org-ql-select test-buffer + '(category) + :sort 'deadline)) + :to-equal num-headings)) + (it "org-ql-query" + (expect (length (org-ql-query :select 'element + :from test-buffer + :where '(category) + :order-by 'date)) + :to-equal num-headings))) + (it "Query pre-processing" (expect (org-ql--pre-process-query '(and "string1" "string2")) :to-equal '(and (regexp "string1") (regexp "string2"))) From 4954789ca5ec33d27d2a353161f8f3da44d782db Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 11:39:04 -0500 Subject: [PATCH 262/970] Add/Change: Use ts.el, add ts-a and ts-i Improves performance, reduces code, and more test cases added. --- README.org | 11 ++- notes.org | 122 +++++++++++++++++++++++++++++++ org-ql.el | 168 ++++++++++--------------------------------- tests/test-org-ql.el | 114 +++++++++++++++++++++++------ 4 files changed, 261 insertions(+), 154 deletions(-) diff --git a/README.org b/README.org index 47a20a5..fee9ab9 100644 --- a/README.org +++ b/README.org @@ -151,9 +151,11 @@ Arguments are listed next to predicate names, where applicable. + ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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). -+ ~ts (&key from to on)~ :: 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. -+ ~ts-active (&key from to on)~ :: Return non-nil if current entry has an active timestamp in given period. If no arguments are specified, return non-nil if entry has any active timestamp. If ~FROM~, return non-nil if entry has an active timestamp on or after ~FROM~. If ~TO~, return non-nil if entry has an active timestamp on or before ~TO~. If ~ON~, return non-nil if entry has an active timestamp on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. -+ ~ts-inactive (&key from to on)~ :: Return non-nil if current entry has an inactive timestamp in given period. If no arguments are specified, return non-nil if entry has any inactive timestamp. If ~FROM~, return non-nil if entry has an inactive timestamp on or after ~FROM~. If ~TO~, return non-nil if entry has an inactive timestamp on or before ~TO~. If ~ON~, return non-nil if entry has an inactive timestamp on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. ++ ~ts (&key from to on type)~ :: 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. ~TYPE~ may be ~active~ to match active timestamps, ~inactive~ to match inactive ones, or ~both~ / nil to match both types. ++ ~ts-active~ :: Like ~ts~ called with ~:type active~. ++ ~ts-a~ :: Like ~ts~ called with ~:type active~. ++ ~ts-inactive~ :: Like ~ts~ called with ~:type inactive~. ++ ~ts-i~ :: Like ~ts~ called with ~:type inactive~. ** Functions / Macros :PROPERTIES: @@ -361,6 +363,8 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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 [[https://github.com/pestctrl/emacs-config/blob/84c557982a860e86d6f67976a82ea776a7bd2c7a/config-org-new.org#my-own-agenda-renderer][Benson Chu's config]].) + 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. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. @@ -375,6 +379,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Internal* + Optimizations for some query selectors, e.g. =regexp= and =todo=. These can provide a significant improvement for some queries. See benchmarks in [[file:notes.org][notes.org]]. ++ Library [[https://github.com/alphapapa/ts.el][ts]] is now used for parsing and comparing timestamps. ** 0.1 diff --git a/notes.org b/notes.org index 6164ac4..0c8591b 100644 --- a/notes.org +++ b/notes.org @@ -647,6 +647,128 @@ If tag inheritance is enabled, we have to check tags on every heading. When it' | preamble: (tags "Emacs") | 2.08 | 0.274555 | 0 | 0 | | no preamble: (tags "Emacs") | slowest | 0.570116 | 0 | 0 | +** 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 + +*** 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 | + +*** :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 | + +*** :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 | + +*** :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 | + ** 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. diff --git a/org-ql.el b/org-ql.el index 7da1473..e51accc 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.2-pre -;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.0") (s "1.12.0")) +;; Package-Requires: ((emacs "26.1") (dash "2.13") (org "9.0") (s "1.12.0") (ts "0.2")) ;; Keywords: hypermedia, outlines, Org, agenda ;;; Commentary: @@ -40,6 +40,7 @@ (require 'subr-x) (require 'dash) +(require 'ts) ;;;; Compatibility @@ -53,6 +54,12 @@ ;;;; Variables +(defconst org-ql-tsr-regexp-inactive + (concat org-ts-regexp-inactive "\\(--?-?" + org-ts-regexp-inactive "\\)?") + ;; MAYBE: Propose this for org.el. + "Regular expression matching an inactive timestamp or timestamp range.") + (defvar org-ql--today nil) (defvar org-ql-use-preamble t @@ -232,7 +239,8 @@ NARROW corresponds to the `org-ql-select' argument NARROW." (defun org-ql--pre-process-query (query) "Return QUERY having been pre-processed. -Replaces bare strings with (regexp) selectors." +Replaces bare strings with (regexp) selectors, and appropriate +`ts'-related selectors." ;; This is unsophisticated, but it works. (cl-labels ((rec (element) (pcase element @@ -244,6 +252,8 @@ Replaces bare strings with (regexp) selectors." ,@(mapcar #'rec clauses))) ;; TODO: Combine (regexp) when appropriate (i.e. inside an OR, not an AND). ((pred stringp) `(regexp ,element)) + (`(,(or 'ts-active 'ts-a) . ,rest) `(ts :type active ,@rest)) + (`(,(or 'ts-inactive 'ts-i) . ,rest) `(ts :type inactive ,@rest)) (_ element)))) (rec query))) @@ -267,39 +277,21 @@ Replaces bare strings with (regexp) selectors." ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' ;; function, not another `clocked'. `(org-ql--predicate-clocked :from ,from :to ,to)) - (ts (&key from to on) + (ts (&key from to on (type 'both)) (when on (setq from on to on)) (when from - (setq from (org-ql--parse-time-string from))) + (setq from (ts-parse-fill 'begin from))) (when to - (setq to (org-ql--parse-time-string to 'end))) + (setq to (ts-parse-fill 'end to))) ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' ;; function, not another `ts'. - `(org-ql--predicate-ts :from ,from :to ,to)) - (ts-active (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-active :from ,from :to ,to)) - (ts-inactive (&key from to on) - (when on - (setq from on - to on)) - (when from - (setq from (org-ql--parse-time-string from))) - (when to - (setq to (org-ql--parse-time-string to 'end))) - ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' - ;; function, not another `ts'. - `(org-ql--predicate-ts-inactive :from ,from :to ,to))) + `(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))))) (cl-symbol-macrolet ((today org-ql--today) ; Necessary because of byte-compiling the lambda (= #'=) (< #'<) @@ -710,9 +702,11 @@ comparator, PRIORITY should be a priority string." ;; and language-independent than using from/to. Alternatively, add :before/:after, but I ;; think the comparators are better. Also consider using a macro to DRY these out. -(org-ql--defpred 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. +(org-ql--defpred ts (&key from to _on regexp) + ;; The underscore before `on' prevents "unused lexical variable" warnings, + ;; because we pre-process that argument in a macro before this function is + ;; called. The `regexp' argument is also provided by the macro and is not + ;; to be given by the user, so it is omitted from the docstring. "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. @@ -725,116 +719,28 @@ 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." +`parse-time-string' but may omit the time value. + +TYPE may be `active' to match active timestamps, `inactive' to +match inactive ones, or `both' / nil to match both types." ;; 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) - (save-excursion - (goto-char (match-beginning 0)) - (org-element-timestamp-parser)))) + `(when (re-search-forward regexp end-pos t) + (ts-parse-org (match-string 0)))) (test-timestamps (pred-form) `(cl-loop for next-ts = (next-timestamp) while next-ts - do (setf beg (float-time (org-timestamp-to-time next-ts)) - end (float-time (org-timestamp-to-time next-ts 'end))) thereis ,pred-form))) (save-excursion - (let ((end-pos (org-entry-end-position)) - beg end) - (cond ((not (or from to)) (next-timestamp)) - ((and from to) (test-timestamps (and (<= beg to) - (>= end from)))) - (from (test-timestamps (<= from end))) - (to (test-timestamps (<= beg to)))))))) - -(org-ql--defpred ts-active (&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 an active timestamp in given period. -If no arguments are specified, return non-nil if entry has any -active timestamp. - -If FROM, return non-nil if entry has an active timestamp on or -after FROM. - -If TO, return non-nil if entry has an active timestamp on or -before TO. - -If ON, return non-nil if entry has an active 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) - (save-excursion - (goto-char (match-beginning 0)) - (org-element-timestamp-parser)))) - (test-timestamps (pred-form) - `(cl-loop for next-ts = (next-timestamp) - while next-ts - when (string-prefix-p "<" next-ts) - do (setf beg (float-time (org-timestamp-to-time next-ts)) - end (float-time (org-timestamp-to-time next-ts 'end))) - thereis ,pred-form))) - (save-excursion - (let ((end-pos (org-entry-end-position)) - beg end) - (cond ((not (or from to)) (next-timestamp)) - ((and from to) (test-timestamps (and (<= beg to) - (>= end from)))) - (from (test-timestamps (<= from end))) - (to (test-timestamps (<= beg to)))))))) - -(org-ql--defpred ts-inactive (&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 an inactive timestamp in given period. -If no arguments are specified, return non-nil if entry has any -inactive timestamp. - -If FROM, return non-nil if entry has an inactive timestamp on or -after FROM. - -If TO, return non-nil if entry has an inactive timestamp on or -before TO. - -If ON, return non-nil if entry has an inactive 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) - (save-excursion - (goto-char (match-beginning 0)) - (org-element-timestamp-parser)))) - (test-timestamps (pred-form) - `(cl-loop for next-ts = (next-timestamp) - while next-ts - when (string-prefix-p "[" next-ts) - do (setf beg (float-time (org-timestamp-to-time next-ts)) - end (float-time (org-timestamp-to-time next-ts 'end))) - thereis ,pred-form))) - (save-excursion - (let ((end-pos (org-entry-end-position)) - beg end) - (cond ((not (or from to)) (next-timestamp)) - ((and from to) (test-timestamps (and (<= beg to) - (>= end from)))) - (from (test-timestamps (<= from end))) - (to (test-timestamps (<= beg to)))))))) + (let ((end-pos (org-entry-end-position))) + (cond ((not (or from to)) (re-search-forward 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)))))))) ;;;;; Date comparison diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 287c7bd..13f7d97 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -169,7 +169,16 @@ RESULTS should be a list of strings as returned by :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"))) - :to-equal '(unless (and (regexp "stringcondition1") (regexp "stringcond2")) (or (regexp "string1") (regexp "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"))) + :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" @@ -412,28 +421,93 @@ RESULTS should be a list of strings as returned by (describe "(ts)" - (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"))) + (describe "active" - (org-ql-it ":from a timestamp" - ;; TODO: Figure out why these take longer than the other (ts) tests. - (org-ql-expect ((ts :from "2017-01-01")) - '("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")) - (org-ql-expect ((ts :from "2019-06-08")) - nil)) + (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-it ":to a timestamp" - (org-ql-expect ((ts :to "2019-06-10")) - '("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")) - (org-ql-expect ((ts :to "2017-07-04")) - '("Skype with president of Antarctica"))) + (org-ql-it ":from a timestamp" + ;; TODO: Figure out why these take longer than the other (ts) tests. + (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-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")) - (org-ql-expect ((ts :on "2019-06-09")) - nil))) + (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-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))) + + (describe "inactive" + + (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"))) + + (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-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")) + (org-ql-expect ((ts :to "2017-07-04" :type inactive)) + 'nil)) + + (org-ql-it ":on a timestamp" + (org-ql-expect ((ts :on "2017-07-05" :type inactive)) + '("Test data" "Learn universal sign language")) + (org-ql-expect ((ts :on "2019-06-09" :type inactive)) + nil))) + + (describe "both" + + (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")) + (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"))) + + (org-ql-it ":from a timestamp" + ;; TODO: Figure out why these take longer than the other (ts) tests. + (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")) + (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")) + (org-ql-expect ((ts :from "2019-06-08")) + nil) + (org-ql-expect ((ts :from "2019-06-08" :type both)) + nil)) + + (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")) + (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")) + (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-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")) + (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")) + (org-ql-expect ((ts :on "2019-06-09")) + nil) + (org-ql-expect ((ts :on "2019-06-09" :type both)) + nil)))) (describe "Compound queries" From a425c45afd563f9b0303fe76ab5a933380574531 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 11 Aug 2019 16:40:05 -0500 Subject: [PATCH 263/970] Add: ts preambles --- notes.org | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ org-ql.el | 9 ++++ 2 files changed, 160 insertions(+) diff --git a/notes.org b/notes.org index 0c8591b..0493271 100644 --- a/notes.org +++ b/notes.org @@ -647,6 +647,157 @@ If tag inheritance is enabled, we have to check tags on every heading. When it' | 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 | + ** 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. diff --git a/org-ql.el b/org-ql.el index e51accc..436c865 100644 --- a/org-ql.el +++ b/org-ql.el @@ -403,6 +403,15 @@ replace the clause with a preamble." t)) ;; Return nil, because we don't need to test the predicate. nil) + (`(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)))) From 1b83c16426d2472e951a9a97887b3754f14be018 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 12 Aug 2019 18:25:42 -0500 Subject: [PATCH 264/970] Notes: Add idea --- notes.org | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/notes.org b/notes.org index 0493271..d7f445b 100644 --- a/notes.org +++ b/notes.org @@ -4,6 +4,10 @@ ** TODO Update commentary +** TODO [#B] Default sort + +Would probably be useful to have a default sort option. + ** TODO ~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: From fbdfe58a086ea315a272b88a0028d9a90b28b904 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 12 Aug 2019 19:22:00 -0500 Subject: [PATCH 265/970] Notes: Add idea and results --- notes.org | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/notes.org b/notes.org index d7f445b..9b3f2d1 100644 --- a/notes.org +++ b/notes.org @@ -1707,3 +1707,42 @@ org-super-agenda--filter-finalize-entries 5 0.1316 | 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* ((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 | 4.03 | 0.275053 | 0 | 0 | +| intersection | slowest | 1.109169 | 0 | 0 | From e97d2c0af3e1d30cecfbc55ea3f3e8e034b76353 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 12 Aug 2019 20:45:44 -0500 Subject: [PATCH 266/970] Add: org-ql-agenda-face --- README.org | 1 + org-ql-agenda.el | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index fee9ab9..e7cd729 100644 --- a/README.org +++ b/README.org @@ -365,6 +365,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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=. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 5423887..93f67f4 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -48,6 +48,12 @@ (when (version< org-version "9.2") (defalias 'org-get-tags #'org-get-tags-at)) +;;;; Faces + +(defface org-ql-agenda-due-date + '((t (:slant italic :weight bold))) + "Face for due dates in `org-ql-agenda' views.") + ;;;; Variables (defvar org-ql-agenda-buffer-name "*Org-QL-Agenda*" @@ -385,7 +391,7 @@ return an empty string." (org-habit-parse-todo)))) (due-string (pcase (org-element-property :relative-due-date element) ('nil "") - (string (format " %s " (org-add-props string nil 'face 'underline))))) + (string (format " %s " (org-add-props string nil 'face 'org-ql-agenda-due-date))))) (string (s-join " " (-non-nil (list todo-keyword priority-string title due-string tag-string))))) (remove-list-of-text-properties 0 (length string) '(line-prefix) string) ;; Add all the necessary properties and faces to the whole string From 5174aca4e8fe956abae7161d15058702bc8874c1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Mon, 12 Aug 2019 20:46:35 -0500 Subject: [PATCH 267/970] Tidy: (org-ql-agenda--format-element) --- org-ql-agenda.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 93f67f4..8b71892 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -377,10 +377,11 @@ return an empty string." (warn "No marker found for item: %s" title) (org-element-property :tags element)) (org-element-property :tags element))) - (tag-string (-some--> tag-list - (s-join ":" it) - (s-wrap it ":") - (org-add-props it nil 'face 'org-tag))) + (tag-string (when tag-list + (--> tag-list + (s-join ":" it) + (s-wrap it ":") + (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) From 2b47e7c7b0ab60bf860e0ce463c44807f88000f9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 13:14:11 -0500 Subject: [PATCH 268/970] Comment: Add FIXME --- org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql.el b/org-ql.el index 436c865..2f87f47 100644 --- a/org-ql.el +++ b/org-ql.el @@ -429,6 +429,8 @@ replace the clause with a preamble." "Return results for ARGS and current buffer using cache." ;; MAYBE: Timeout cached queries. Probably not necessarily since they will be removed when a ;; buffer is closed, or when a query is run after modifying a buffer. + ;; FIXME: Narrowed queries should conflict in the cache, because the region is not + ;; stored. We should either not cache narrow queries, or store the region with it. (-let (((&plist :query query :action action :narrow narrow) args)) (if-let* ((buffer-cache (gethash (current-buffer) org-ql-cache)) (query-cache (cadr buffer-cache)) From b641e6d53cfc6b4655a34ea9de8b5d3fe275a040 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 13:19:08 -0500 Subject: [PATCH 269/970] Comment: Add TODO --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index 2f87f47..daed79a 100644 --- a/org-ql.el +++ b/org-ql.el @@ -395,6 +395,7 @@ replace the clause with a preamble." (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "SCHEDULED" ":") t)) ;; Return element, because the predicate still needs testing. element) + ;; TODO: Add selector for tags without inheritance. ((and `(tags . ,tags) (guard (not org-use-tag-inheritance))) ;; When tag inheritance is disabled, we only consider direct tags, ;; so we can search directly to headings containing one of the tags. From 31bc01bc52c584b0f4d29e51e0241b8ccac6bde2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 13:48:56 -0500 Subject: [PATCH 270/970] Fix: (org-ql--pre-process-query) Process (not) clauses --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index daed79a..49dfc8e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -246,6 +246,7 @@ Replaces bare strings with (regexp) selectors, and appropriate (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) From 515b4960c40e6ed6dd5ab404c2bc133fa1225ec7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 13:57:34 -0500 Subject: [PATCH 271/970] Change: (todo) Don't match done tasks --- README.org | 3 ++- org-ql.el | 2 +- tests/test-org-ql.el | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index e7cd729..ad6d25f 100644 --- a/README.org +++ b/README.org @@ -150,7 +150,7 @@ Arguments are listed next to predicate names, where applicable. + ~regexp (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). + ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). -+ ~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). ++ ~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~). + ~ts (&key from to on type)~ :: 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. ~TYPE~ may be ~active~ to match active timestamps, ~inactive~ to match inactive ones, or ~both~ / nil to match both types. + ~ts-active~ :: Like ~ts~ called with ~:type active~. + ~ts-a~ :: Like ~ts~ called with ~:type active~. @@ -370,6 +370,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *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~). *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) diff --git a/org-ql.el b/org-ql.el index 49dfc8e..591031e 100644 --- a/org-ql.el +++ b/org-ql.el @@ -600,7 +600,7 @@ ignored." 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 t) + (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))))) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 13f7d97..a97d875 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -382,10 +382,9 @@ RESULTS should be a list of strings as returned by (describe "(todo)" (org-ql-it "without arguments" - ;; FIXME: This returns an item that is done, which is incorrect. (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" "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"))) + '("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" ;; FIXME: Figure out why this takes >10x longer than the other (todo) From 76debff1c5960d2f4118928a88e7f25cb6deb02b Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 13:59:53 -0500 Subject: [PATCH 272/970] Add: Selectors (children) and (descendants) --- README.org | 10 ++++++++++ org-ql.el | 31 +++++++++++++++++++++++++++++++ tests/test-org-ql.el | 23 +++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/README.org b/README.org index ad6d25f..32dada2 100644 --- a/README.org +++ b/README.org @@ -73,6 +73,13 @@ More examples are available in [[examples.org]]. (tags "Emacs") (priority "A"))) (agenda))))) + + ;; Show a "stuck projects" view: tasks that are not done and have only + ;; non-task children. + (org-ql-agenda (org-agenda-files) + (and (todo) + (children) + (not (children (todo))))) #+END_SRC * Usage @@ -136,10 +143,12 @@ A query is a lisp form which may contain arbitrary lisp forms, as well as certai 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. + ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. + ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~; or if omitted, it is determined automatically using ~org-deadline-warning-days~. ~COMPARATOR~ should be a function (like ~<=~). ++ ~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 (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). @@ -366,6 +375,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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)~. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql.el b/org-ql.el index 591031e..377db58 100644 --- a/org-ql.el +++ b/org-ql.el @@ -253,6 +253,11 @@ Replaces bare strings with (regexp) selectors, and appropriate ,@(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))) (`(,(or 'ts-active 'ts-a) . ,rest) `(ts :type active ,@rest)) (`(,(or 'ts-inactive 'ts-i) . ,rest) `(ts :type inactive ,@rest)) (_ element)))) @@ -549,6 +554,32 @@ empty time values to 23:59:59; otherwise, to 00:00:00." ;;;;; Predicates +(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))))) + (org-ql-select (current-buffer) + query :narrow t :action (lambda () t))))))) + +(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) + (org-ql-select (current-buffer) + query :narrow t :action (lambda () t)))))) + (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. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index a97d875..245aa2c 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -219,6 +219,29 @@ RESULTS should be a list of strings as returned by (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)) + '("Test data" "Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Recurring" "Ideas" "Code" "Misc"))) + (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")))) + + (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"))) + (org-ql-it "with sub-query" + (org-ql-expect ((descendants (todo "CHECK"))) + '("Test data" "Recurring"))) + (org-ql-it "with granddescendants query" + (org-ql-expect ((descendants (descendants "moon"))) + '("Test data" "Take over the universe" "Take over the moon" "Code")))) + (describe "(clocked)" (org-ql-it "without arguments" From b634647e466a7b25effddfbc535d61251c6629df Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 14:37:27 -0500 Subject: [PATCH 273/970] Fix: (org-ql--select) Don't search buffers without headings Especially important when using org-ql-search to search "all" Org buffers. --- README.org | 1 + org-ql.el | 26 +++++++++++++++++--------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/README.org b/README.org index 32dada2..38a79e2 100644 --- a/README.org +++ b/README.org @@ -385,6 +385,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) + Don't overwrite bindings in =org-agenda-mode-map=. ++ Don't search buffers without headings, and show a message if the user attempts it. *Compatibility* + Fixes for compatibility with Org 9.2. (Thanks to [[https://github.com/ataias][Ataias Pereira Reis]] and [[https://github.com/dakra][Daniel Kraus]].) diff --git a/org-ql.el b/org-ql.el index 377db58..ca38445 100644 --- a/org-ql.el +++ b/org-ql.el @@ -487,15 +487,23 @@ If NARROW is non-nil, buffer will not be widened." (goto-char (point-min)) (when (org-before-first-heading-p) (outline-next-heading)) - ;; `cl-loop' makes this double-while much clearer than the expanded form. - (cond (preamble-re (cl-loop while (re-search-forward preamble-re 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))))))) + (if (not (org-at-heading-p)) + (progn + ;; No headings in buffer: return nil. + (unless (string-prefix-p " " (buffer-name)) + ;; Not a special, hidden buffer: show message, because if a user accidentally + ;; searches a buffer without headings, he might be confused. + (message "org-ql: No headings in buffer: %s" (current-buffer))) + nil) + ;; `cl-loop' makes this double-while much clearer than the expanded form. + (cond (preamble-re (cl-loop while (re-search-forward preamble-re 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)))))))) (--each orig-fns ;; Restore original function mappings. (fset (plist-get it :name) (plist-get it :fn)))))) From 3856e61800a12553c2d75213f261b7435bdfad01 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 15:05:47 -0500 Subject: [PATCH 274/970] Fix: (org-ql-select) Don't search hidden/special buffers --- README.org | 1 + org-ql.el | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index 38a79e2..2726fdd 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 + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) + 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. *Compatibility* + Fixes for compatibility with Org 9.2. (Thanks to [[https://github.com/ataias][Ataias Pereira Reis]] and [[https://github.com/dakra][Daniel Kraus]].) diff --git a/org-ql.el b/org-ql.el index ca38445..c3e370c 100644 --- a/org-ql.el +++ b/org-ql.el @@ -156,7 +156,9 @@ non-nil." ;; It feels unintuitive that `find-file-noselect' returns ;; a buffer if the filename doesn't exist. (find-file-noselect it)) - (user-error "Can't open file: %s" it))))))) + (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 preamble-re) (org-ql--query-preamble query)) (predicate (org-ql--query-predicate query)) From 559764aeddf7fdff77530061f237fa4a6ae6fb1e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 15:38:47 -0500 Subject: [PATCH 275/970] Comment: Remove task Basically done. Also, I think :from/:to/:on are ultimately better than numeric comparators like <=, because it's easier to express a range of dates. --- org-ql.el | 4 ---- 1 file changed, 4 deletions(-) diff --git a/org-ql.el b/org-ql.el index c3e370c..1b0970b 100644 --- a/org-ql.el +++ b/org-ql.el @@ -751,10 +751,6 @@ comparator, PRIORITY should be a priority string." ;;;;;; Timestamps -;; TODO: Move active/inactive into (ts) predicate, allowing the first arg to be either -;; inactive/active or the comparator. Using numeric comparators is more powerful, concise, -;; and language-independent than using from/to. Alternatively, add :before/:after, but I -;; think the comparators are better. Also consider using a macro to DRY these out. (org-ql--defpred ts (&key from to _on regexp) ;; The underscore before `on' prevents "unused lexical variable" warnings, From 9f8101779cab91fdfe157d82bfd8fbd125527d49 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 16:08:10 -0500 Subject: [PATCH 276/970] Change: (ts) Accept ts structs --- README.org | 2 +- org-ql.el | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.org b/README.org index 2726fdd..60c6beb 100644 --- a/README.org +++ b/README.org @@ -160,7 +160,7 @@ Arguments are listed next to predicate names, where applicable. + ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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~). -+ ~ts (&key from to on type)~ :: 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. ~TYPE~ may be ~active~ to match active timestamps, ~inactive~ to match inactive ones, or ~both~ / nil to match both types. ++ ~ts (&key from to on type)~ :: 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 either ~ts~ structs, or strings parseable by ~parse-time-string~ which may omit the time value. ~TYPE~ may be ~active~ to match active timestamps, ~inactive~ to match inactive ones, or ~both~ / nil to match both types. + ~ts-active~ :: Like ~ts~ called with ~:type active~. + ~ts-a~ :: Like ~ts~ called with ~:type active~. + ~ts-inactive~ :: Like ~ts~ called with ~:type inactive~. diff --git a/org-ql.el b/org-ql.el index 1b0970b..a7757cb 100644 --- a/org-ql.el +++ b/org-ql.el @@ -290,9 +290,13 @@ Replaces bare strings with (regexp) selectors, and appropriate (setq from on to on)) (when from - (setq from (ts-parse-fill 'begin from))) + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) (when to - (setq to (ts-parse-fill 'end to))) + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) ;; NOTE: The macro must expand to the actual `org-ql--predicate-ts' ;; function, not another `ts'. `(org-ql--predicate-ts :from ,from :to ,to @@ -768,8 +772,8 @@ 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. +FROM, TO, and ON should be either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value. TYPE may be `active' to match active timestamps, `inactive' to match inactive ones, or `both' / nil to match both types." From 1d69ab7b203ff3d7f6dd2478224c9aabaeb4876c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 16:26:56 -0500 Subject: [PATCH 277/970] Fix: (org-ql-query) Indentation declaration --- org-ql.el | 1 + 1 file changed, 1 insertion(+) diff --git a/org-ql.el b/org-ql.el index a7757cb..f077653 100644 --- a/org-ql.el +++ b/org-ql.el @@ -234,6 +234,7 @@ ORDER-BY corresponds to the `org-ql-select' argument SORT, which see. NARROW corresponds to the `org-ql-select' argument NARROW." + (declare (indent 0)) (org-ql-select from where :action select :narrow narrow From 40b36ecad20684b118ba9da3ca22c12488a2cef4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 17:02:38 -0500 Subject: [PATCH 278/970] Comment: Add TODO --- org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/org-ql.el b/org-ql.el index f077653..2852157 100644 --- a/org-ql.el +++ b/org-ql.el @@ -970,6 +970,8 @@ PREDICATES is a list of one or more sorting methods, including: (-sort (sorter pred) items))) finally return items))) +;; TODO: Rewrite date sorters using `ts'. + (defun org-ql--date-type< (type a b) "Return non-nil if A's date of TYPE is earlier than B's. A and B are Org headline elements. TYPE should be a symbol like From 6b9b985c1e0373be9ed7d528131d3b7a4253bfd2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 17:06:39 -0500 Subject: [PATCH 279/970] Change: Use ts for all timestamp-related selectors This is much simpler, and it seems quite fast with the preambles. --- README.org | 32 ++-- org-ql.el | 391 +++++++++++++++++++++---------------------- tests/test-org-ql.el | 130 ++++++++------ 3 files changed, 293 insertions(+), 260 deletions(-) diff --git a/README.org b/README.org index 60c6beb..671810c 100644 --- a/README.org +++ b/README.org @@ -144,27 +144,34 @@ 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. -+ ~clocked (&key from to on)~ :: 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. If ~FROM~, return non-nil if entry was clocked on or after ~FROM~. If ~TO~, return non-nil if entry was clocked on or before ~TO~. If ~ON~, return non-nil if entry was clocked on date ~ON~. ~FROM~, ~TO~, and ~ON~ should be strings parseable by ~parse-time-string~ but may omit the time value. Note: Clock entries are expected to be clocked out. Currently clocked entries (i.e. with unclosed timestamp ranges) are ignored. -+ ~closed (&optional comparator target-date)~ :: Return non-nil if entry's closed date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~date (&optional comparator target-date type)~ :: Return non-nil if Org entry at point has date of ~TYPE~ that compares with ~TARGET-DATE~ using ~COMPARATOR~. Checks all Org-formatted timestamp strings in entry. ~TYPE~ may be ~active~, ~inactive~, or ~all~, to control whether active, inactive, or all timestamps are checked. Ranges of each type are also checked. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). -+ ~deadline (&optional comparator target-date)~ :: Return non-nil if entry's deadline compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~; or if omitted, it is determined automatically using ~org-deadline-warning-days~. ~COMPARATOR~ should be a function (like ~<=~). + ~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 (regexp)~ :: Return non-nil if current entry's heading matches ~REGEXP~ (a regexp string). + ~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 ~>=~. -+ ~planning (&optional comparator target-date)~ :: Return non-nil if entry's planning date (deadline or scheduled) compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~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. + ~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 (regexp)~ :: Return non-nil if current entry matches ~REGEXP~ (a regexp string). -+ ~scheduled (&optional comparator target-date)~ :: Return non-nil if entry's scheduled date compares with ~TARGET-DATE~ using ~COMPARATOR~. ~TARGET-DATE~ should be a string parseable by ~date-to-day~. ~COMPARATOR~ should be a function (like ~<=~). + ~tags (&optional tags)~ :: Return non-nil if current heading has one or more of ~TAGS~ (a list of strings). + ~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~). -+ ~ts (&key from to on type)~ :: 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 either ~ts~ structs, or strings parseable by ~parse-time-string~ which may omit the time value. ~TYPE~ may be ~active~ to match active timestamps, ~inactive~ to match inactive ones, or ~both~ / nil to match both types. -+ ~ts-active~ :: Like ~ts~ called with ~:type active~. -+ ~ts-a~ :: Like ~ts~ called with ~:type active~. -+ ~ts-inactive~ :: Like ~ts~ called with ~:type inactive~. -+ ~ts-i~ :: Like ~ts~ called with ~:type inactive~. + +*** Date/time selectors +:PROPERTIES: +:TOC: ignore +:END: + +All of these selectors 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 ~ts~ structs, or strings parseable by ~parse-time-string~ which may omit the time value. + ++ ~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. ++ ~deadline~ :: Return non-nil if current entry has deadline in given period. 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. ++ ~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~ :: Like ~ts~, but only matches active timestamps. ++ ~ts-a~ :: Like ~ts~, but only matches active timestamps. ++ ~ts-inactive~ :: Like ~ts~, but only matches inactive timestamps. ++ ~ts-i~ :: Like ~ts~, but only matches inactive timestamps. ** Functions / Macros :PROPERTIES: @@ -382,6 +389,9 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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~). +*Removed* ++ Selector ~(date)~, replaced by ~(ts)~. + *Fixed* + Handle date ranges in date-based selectors. (Thanks to [[https://github.com/codygman][Cody Goodman]], [[https://github.com/swflint][Samuel W. Flint]], and [[https://github.com/vikasrawal][Vikas Rawal]].) + Don't overwrite bindings in =org-agenda-mode-map=. diff --git a/org-ql.el b/org-ql.el index 2852157..f5bcebf 100644 --- a/org-ql.el +++ b/org-ql.el @@ -52,7 +52,9 @@ (defun org-ql--get-tags (&optional pos local) (org-get-tags pos local))) -;;;; Variables +;;;; Constants + +;; Note the use of the `rx' `blank' keyword, which matches "horizontal" whitespace. (defconst org-ql-tsr-regexp-inactive (concat org-ts-regexp-inactive "\\(--?-?" @@ -60,6 +62,19 @@ ;; MAYBE: Propose this for org.el. "Regular expression matching an inactive timestamp or timestamp range.") +(defconst org-ql-clock-regexp + (rx bol (0+ blank) "CLOCK:" (group (1+ not-newline))) + "Regular expression matching Org \"CLOCK:\" lines. +Like `org-clock-line-re', but matches the timestamp range in a +match group.") + +(defconst org-ql-planning-regexp + (rx bol (0+ blank) (or "CLOSED" "DEADLINE" "SCHEDULED") ":" (1+ blank) (group (1+ not-newline))) + "Regular expression matching Org \"planning\" lines. +That is, \"CLOSED:\", \"DEADLINE:\", or \"SCHEDULED:\".") + +;;;; Variables + (defvar org-ql--today nil) (defvar org-ql-use-preamble t @@ -275,17 +290,84 @@ Replaces bare strings with (regexp) selectors, and appropriate ;; for now. Most importantly, it works! (let (from to on) ;; TODO: DRY these macrolets. + ;; MAYBE: Instead of defining clocked, closed, etc. as predicates, + ;; rewrite them to call --predicate-ts directly here. Only drawback, + ;; I think, is that it would make documentation less automated. (cl-macrolet ((clocked (&key from to on) (when on (setq from on to on)) (when from - (setq from (org-ql--parse-time-string from))) + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) (when to - (setq to (org-ql--parse-time-string to 'end))) + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) ;; NOTE: The macro must expand to the actual `org-ql--predicate-clocked' ;; function, not another `clocked'. `(org-ql--predicate-clocked :from ,from :to ,to)) + (closed (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) + (when to + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-closed' + ;; function, not another `closed'. + `(org-ql--predicate-closed :from ,from :to ,to)) + (deadline (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) + (when to + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-deadline' + ;; function, not another `deadline'. + `(org-ql--predicate-deadline :from ,from :to ,to)) + (planning (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) + (when to + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-planning' + ;; function, not another `planning'. + `(org-ql--predicate-planning :from ,from :to ,to)) + (scheduled (&key from to on) + (when on + (setq from on + to on)) + (when from + (setq from (cl-typecase from + (string (ts-parse-fill 'begin from)) + (ts from)))) + (when to + (setq to (cl-typecase to + (string (ts-parse-fill 'end to)) + (ts to)))) + ;; NOTE: The macro must expand to the actual `org-ql--predicate-scheduled' + ;; function, not another `scheduled'. + `(org-ql--predicate-scheduled :from ,from :to ,to)) (ts (&key from to on (type 'both)) (when on (setq from on @@ -327,22 +409,15 @@ replace the clause with a preamble." element) (pcase element (`(or _) element) - (`(closed . ,_) - (setq org-ql-preamble - (rx-to-string `(seq bol (0+ (any " ")) "CLOSED" ":" (1+ space) (1+ not-newline)) t)) - ;; Return element, because the predicate still needs testing. + (`(clocked . ,_) + (setq org-ql-preamble org-ql-clock-regexp) element) - (`(closed) - (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "CLOSED" ":") t)) + (`(closed . ,_) + (setq org-ql-preamble org-closed-time-regexp) ;; Return element, because the predicate still needs testing. element) (`(deadline . ,_) - (setq org-ql-preamble - (rx-to-string `(seq bol (0+ (any " ")) "DEADLINE" ":" (1+ space) (1+ not-newline)) t)) - ;; Return element, because the predicate still needs testing. - element) - (`(deadline) - (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "DEADLINE" ":") t)) + (setq org-ql-preamble org-deadline-time-regexp) ;; Return element, because the predicate still needs testing. element) (`(regexp . ,regexps) @@ -360,6 +435,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))) nil) @@ -376,6 +452,10 @@ replace the clause with a preamble." (`(level ,num) (setq org-ql-preamble (rx-to-string `(seq bol (repeat ,num "*") " ") t)) nil) + (`(planning . ,_) + (setq org-ql-preamble org-ql-planning-regexp) + ;; Return element, because the predicate still needs testing. + element) (`(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. @@ -400,12 +480,7 @@ replace the clause with a preamble." ;; (1+ space) (minimal-match (1+ not-newline)) eol))) ;; element) (`(scheduled . ,_) - (setq org-ql-preamble - (rx-to-string `(seq bol (0+ (any " ")) "SCHEDULED" ":" (1+ space) (1+ not-newline)) t)) - ;; Return element, because the predicate still needs testing. - element) - (`(scheduled) - (setq org-ql-preamble (rx-to-string `(seq bol (0+ (any " ")) "SCHEDULED" ":") t)) + (setq org-ql-preamble org-scheduled-time-regexp) ;; Return element, because the predicate still needs testing. element) ;; TODO: Add selector for tags without inheritance. @@ -595,45 +670,6 @@ empty time values to 23:59:59; otherwise, to 00:00:00." (org-ql-select (current-buffer) query :narrow t :action (lambda () t)))))) -(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. - "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. - -If FROM, return non-nil if entry was clocked on or after FROM. -If TO, return non-nil if entry was clocked on or before TO. -If ON, return non-nil if entry was clocked on date ON. - -FROM, TO, and ON should be strings parseable by -`parse-time-string' but may omit the time value. - -Note: Clock entries are expected to be clocked out. Currently -clocked entries (i.e. with unclosed timestamp ranges) are -ignored." - ;; 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-clock-line-re end-pos t) - (org-element-property :value (org-element-context)))) - (test-timestamps (pred-form) - `(cl-loop for next-ts = (next-timestamp) - while next-ts - ;; Using `setf' instead of `for beg =` here prevents "unused lexical variable" warnings. - do (setf beg (float-time (org-timestamp-to-time next-ts)) - end (float-time (org-timestamp-to-time next-ts 'end))) - thereis ,pred-form))) - (save-excursion - (let ((end-pos (org-entry-end-position)) - beg end) - (cond ((not (or from to)) (next-timestamp)) - ((and from to) (test-timestamps (and (<= beg to) - (>= end from)))) - (from (test-timestamps (<= from end))) - (to (test-timestamps (<= beg to)))))))) - (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)))) @@ -756,8 +792,102 @@ comparator, PRIORITY should be a priority string." ;;;;;; Timestamps +(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. + "Return non-nil if current entry was clocked in given period. +If no arguments are specified, return non-nil if entry has any +timestamp. -(org-ql--defpred ts (&key from to _on regexp) +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 either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value." + (org-ql--predicate-ts :from from :to to :regexp org-ql-clock-regexp :match-group 1)) + +(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. + "Return non-nil if current entry was closed 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 either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value." + (org-ql--predicate-ts :from from :to to :regexp org-closed-time-regexp :match-group 1)) + +(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. + "Return non-nil if current entry has deadline 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 either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value." + (org-ql--predicate-ts :from from :to to :regexp org-deadline-time-regexp :match-group 1)) + +(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. + "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 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 either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value." + (org-ql--predicate-ts :from from :to to :regexp org-ql-planning-regexp :match-group 1)) + +(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. + "Return non-nil if current entry is scheduled 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 either `ts' structs, or strings +parseable by `parse-time-string' which may omit the time value." + (org-ql--predicate-ts :from from :to to :regexp org-scheduled-time-regexp :match-group 1)) + +(org-ql--defpred ts (&key from to _on regexp (match-group 0)) ;; The underscore before `on' prevents "unused lexical variable" warnings, ;; because we pre-process that argument in a macro before this function is ;; called. The `regexp' argument is also provided by the macro and is not @@ -784,7 +914,7 @@ match inactive ones, or `both' / nil to match both types." ;; FIXME: This assumes every "clocked" entry is a range. Unclosed clock entries are not handled. (cl-macrolet ((next-timestamp () `(when (re-search-forward regexp end-pos t) - (ts-parse-org (match-string 0)))) + (ts-parse-org (match-string match-group)))) (test-timestamps (pred-form) `(cl-loop for next-ts = (next-timestamp) while next-ts @@ -797,143 +927,6 @@ match inactive ones, or `both' / nil to match both types." (from (test-timestamps (ts<= from next-ts))) (to (test-timestamps (ts<= next-ts to)))))))) -;;;;; Date comparison - -(defun org-ql--date-type-p (type &optional comparator target-date) - "Return non-nil if current heading has a date property of TYPE. -TYPE should be a keyword symbol, like :scheduled or :deadline. - -With COMPARATOR and TARGET-DATE, return non-nil if entry's -scheduled date compares with TARGET-DATE according to COMPARATOR. -TARGET-DATE may be a string like \"2017-08-05\", or an integer -like one returned by `date-to-day'." - (when-let (;; FIXME: Add :date selector, since I put it - ;; in the examples but forgot to actually - ;; make it. - (timestamp (org-entry-get (point) (pcase type - (:deadline "DEADLINE") - (:scheduled "SCHEDULED") - (:closed "CLOSED")))) - (date-element (with-temp-buffer - ;; FIXME: Hack: since we're using - ;; (org-element-property :type date-element) - ;; below, we need this date parsed into an - ;; org-element element - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)))) - (pcase comparator - ;; Not comparing, just checking if it has one - ('nil t) - ;; Compare dates - ((pred functionp) - (let ((target-day-number (cl-typecase target-date - (null (+ (org-get-wdays timestamp) (org-today))) - ;; Append time to target-date because `date-to-day' requires it. - (string (date-to-day (concat target-date " 00:00"))) - (integer target-date)))) - (pcase (org-element-property :type date-element) - ((or 'active 'inactive 'active-range 'inactive-range) - (funcall comparator - (org-time-string-to-absolute - (org-element-timestamp-interpreter date-element 'ignore)) - target-day-number)) - (_ (error "Unknown date-element type \"%s\" in buffer %s at position %s" - (org-element-property :type date-element) (current-buffer) (point)))))) - (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" - comparator target-date))))) - -(org-ql--defpred planning (&optional comparator target-date) - "Return non-nil if entry's planning date (deadline or scheduled) compares with TARGET-DATE using COMPARATOR. -TARGET-DATE should be a string parseable by `date-to-day'. -COMPARATOR should be a function (like `<=')." - ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. - ;; FIXME: I think :date selects either :deadline, :scheduled, or :closed, but I'm not sure. - (org-ql--date-type-p :date comparator target-date)) - -(org-ql--defpred deadline (&optional comparator target-date) - "Return non-nil if entry's deadline compares with TARGET-DATE using COMPARATOR. -TARGET-DATE should be a string parseable by `date-to-day'; or if -omitted, it is determined automatically using -`org-deadline-warning-days'. COMPARATOR should be a -function (like `<=')." - ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. - ;; FIXME: This is slightly confusing. Using plain (deadline) does, and should, select entries - ;; that have any deadline. But the common case of wanting to select entries whose deadline is - ;; within the warning days (either the global setting or that entry's setting) requires the user - ;; to specify the <= comparator, which is unintuitive. Maybe it would be better to use that - ;; comparator by default, and use an 'any comparator to select entries with any deadline. Of - ;; course, that would make the deadline selector different from the scheduled, closed, and date - ;; selectors, which would also be unintuitive. - (org-ql--date-type-p :deadline comparator target-date)) - -(org-ql--defpred scheduled (&optional comparator target-date) - "Return non-nil if entry's scheduled date compares with TARGET-DATE using COMPARATOR. -TARGET-DATE should be a string parseable by `date-to-day'. -COMPARATOR should be a function (like `<=')." - ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. - (org-ql--date-type-p :scheduled comparator target-date)) - -(org-ql--defpred closed (&optional comparator target-date) - "Return non-nil if entry's closed date compares with TARGET-DATE using COMPARATOR. -TARGET-DATE should be a string parseable by `date-to-day'. -COMPARATOR should be a function (like `<=')." - ;; NOTE: This was a defsubst before being defined with the macro. Might be good to make it a defsubst again. - (org-ql--date-type-p :closed comparator target-date)) - -(org-ql--defpred date (&optional comparator target-date (type 'active)) - "Return non-nil if Org entry at point has date of TYPE that compares with TARGET-DATE using COMPARATOR. -Checks all Org-formatted timestamp strings in entry. TYPE may be -`active', `inactive', or `all', to control whether active, -inactive, or all timestamps are checked. Ranges of each type are -also checked. TARGET-DATE should be a string parseable by -`date-to-day'. COMPARATOR should be a function (like `<=')." - ;; TODO: Deprecate this with a warning, suggest using (ts) instead, and remove (date) from examples. - ;; MAYBE: This duplicates some code in --date-p, maybe it could be refactored DRYer. - (let* ((entry-timestamps (save-excursion - ;; NOTE: It's important to `save-excursion', otherwise the point will be moved, which will - ;; likely cause the action function to fail. We could wrap the call to the predicate in - ;; `save-excursion', but that would do it even when not necessary, which would be slower. - (cl-loop while (re-search-forward org-element--timestamp-regexp (org-entry-end-position) t) - collect (match-string 0))))) - (pcase comparator - ('nil (pcase type - ('all entry-timestamps) - ('active (cl-loop for timestamp in entry-timestamps - thereis (string-prefix-p "<" timestamp))) - ('inactive (cl-loop for timestamp in entry-timestamps - thereis (string-prefix-p "[" timestamp))) - (_ (user-error "Invalid type for date selector. May be `active', `inactive', or `all'")))) - ((pred functionp) - ;; TODO: Avoid computing target-day-number every time this is called. - ;; Probably need to make a lambda that has it already defined. - (let ((target-day-number (cl-typecase target-date - (null nil) ; Calculated later. - ;; Append time to target-date because `date-to-day' requires it. - (string (date-to-day (concat target-date " 00:00"))) - (integer target-date)))) - (cl-loop for timestamp in entry-timestamps - for date-element = (with-temp-buffer - ;; MAYBE: Replace with ts.el eventually. - ;; TODO: Parse the element in the re-search-forward loop. - (insert timestamp) - (goto-char 0) - (org-element-timestamp-parser)) - for this-target-day-number = (or target-day-number - ;; FIXME: Not sure if it makes sense to check warning - ;; days for non-planning timestamps, but we'll try it. - (+ (org-get-wdays timestamp) (org-today))) - thereis (when (or (eq 'all type) - (member (org-element-property :type date-element) - (pcase type - ('active '(active active-range)) - ('inactive '(inactive inactive-range))))) - (funcall comparator (org-time-string-to-absolute - (org-element-timestamp-interpreter date-element 'ignore)) - this-target-day-number))))) - (_ (user-error "COMPARATOR (%s) must be a function, and DATE (%s) must be a string or day-number integer" - comparator target-date))))) - ;;;;; Sorting ;; FIXME: These appear to work properly, but it would be good to have tests for them. diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index 245aa2c..df4a917 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -280,39 +280,26 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((closed)) '("Learn universal sign language"))) - (org-ql-it "=" - (org-ql-expect ((closed = "2017-07-05")) + (org-ql-it ":on" + (org-ql-expect ((closed :on "2017-07-05")) '("Learn universal sign language")) - (org-ql-expect ((closed = "2019-06-09")) + (org-ql-expect ((closed :on "2019-06-09")) nil)) - (org-ql-it "<" - ;; TODO: Figure out why these tests take about 8 times longer than the other comparators in the (closed) tests. - (org-ql-expect ((closed < "2019-06-10")) + (org-ql-it ":from" + (org-ql-expect ((closed :from "2017-07-04")) '("Learn universal sign language")) - (org-ql-expect ((closed < "2017-06-10")) + (org-ql-expect ((closed :from "2017-07-05")) + '("Learn universal sign language")) + (org-ql-expect ((closed :from "2017-07-06")) nil)) - (org-ql-it ">" - (org-ql-expect ((closed > "2017-07-04")) - '("Learn universal sign language")) - (org-ql-expect ((closed > "2019-07-05")) - nil)) - - (org-ql-it ">=" - (org-ql-expect ((closed >= "2017-07-04")) - '("Learn universal sign language")) - (org-ql-expect ((closed >= "2017-07-05")) - '("Learn universal sign language")) - (org-ql-expect ((closed >= "2017-07-06")) - nil)) - - (org-ql-it "<=" - (org-ql-expect ((closed <= "2017-07-04")) + (org-ql-it ":to" + (org-ql-expect ((closed :to "2017-07-04")) nil) - (org-ql-expect ((closed <= "2017-07-05")) + (org-ql-expect ((closed :to "2017-07-05")) '("Learn universal sign language")) - (org-ql-expect ((closed <= "2017-07-06")) + (org-ql-expect ((closed :to "2017-07-06")) '("Learn universal sign language")))) (describe "(deadline)" @@ -321,41 +308,28 @@ RESULTS should be a list of strings as returned by (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 "=" - (org-ql-expect ((deadline = "2017-07-05")) + (org-ql-it ":on" + (org-ql-expect ((deadline :on "2017-07-05")) '("/r/emacs")) - (org-ql-expect ((deadline = "2019-06-09")) + (org-ql-expect ((deadline :on "2019-06-09")) nil)) - (org-ql-it "<" - (org-ql-expect ((deadline < "2019-06-10")) + (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 < "2017-06-10")) - nil)) - - (org-ql-it ">" - ;; TODO: Figure out why these tests take much longer than e.g. the (deadline <) tests. - (org-ql-expect ((deadline > "2017-07-04 00:00")) + (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 > "2019-07-05")) - nil)) - - (org-ql-it ">=" - (org-ql-expect ((deadline >= "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 >= "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 >= "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 >= "2018-07-06")) + (org-ql-expect ((deadline :from "2018-07-06")) nil)) - (org-ql-it "<=" - (org-ql-expect ((deadline <= "2017-07-04")) + (org-ql-it ":to" + (org-ql-expect ((deadline :to "2017-07-04")) nil) - (org-ql-expect ((deadline <= "2017-07-05")) + (org-ql-expect ((deadline :to "2017-07-05")) '("/r/emacs")) - (org-ql-expect ((deadline <= "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-it "(done)" @@ -366,6 +340,34 @@ RESULTS should be a list of strings as returned by (org-ql-expect ((habit)) '("Practice leaping tall buildings in a single bound"))) + (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-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-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-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")))) + (describe "(property)" ;; MAYBE: Add support for (property) without arguments. @@ -402,6 +404,34 @@ RESULTS should be a list of strings as returned by :sort todo) '("Take over the universe" "Take over the world" "Take over Mars" "Take over the moon" "Order a pizza" "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-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-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-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")))) + (describe "(todo)" (org-ql-it "without arguments" From 62e948619a6a1d45c0c5f6edbeb83908b667726a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 17:19:01 -0500 Subject: [PATCH 280/970] Docs: Add example org-ql-agenda-last-days --- examples.org | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/examples.org b/examples.org index 5873c8b..316543d 100644 --- a/examples.org +++ b/examples.org @@ -1,5 +1,34 @@ * Examples +** Show entries with timestamps in the last N days + +#+BEGIN_SRC elisp + (cl-defun org-ql-agenda-last-days (days &optional (type 'ts)) + "Show entries from previous DAYS days with timestamps of TYPE. + TYPE may be `ts', `ts-active', `ts-inactive', `clocked', + `closed', `deadline', `planning', or `scheduled'." + (interactive (list (read-number "Days: ") + (->> '(ts ts-active ts-inactive clocked closed deadline planning scheduled) + (completing-read "Timestamp type: ") + intern))) + (let ((from (->> (ts-now) + (ts-adjust 'day (* -1 days)) + (ts-apply :hour 0 :minute 0 :second 0) + ;; Formatting isn't required, but it looks better in the header than a struct. + ts-format))) + (org-ql-search (org-agenda-files) + `(,type :from ,from :to ,(ts-now))))) + + ;; Show entries with any timestamp from last 7 days: + (org-ql-agenda-last-days 7) + + ;; Show entries clocked in last 7 days: + (org-ql-agenda-last-days 30 'clocked) + + ;; Show entries closed in last 7 days: + (org-ql-agenda-last-days 30 'closed) +#+END_SRC + ** Listing bills coming due This uses the example in the readme file, but maps across the elements returned by ~org-ql~ to present a simple list of titles and deadlines. From a5b06dc1bfe158d0b3121fe37fb7c14c238113c2 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 17:36:12 -0500 Subject: [PATCH 281/970] Docs: Add installation instructions --- README.org | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.org b/README.org index 671810c..ad78156 100644 --- a/README.org +++ b/README.org @@ -13,6 +13,7 @@ :TOC: this :END: - [[#examples][Examples]] + - [[#installation][Installation]] - [[#usage][Usage]] - [[#commands][Commands]] - [[#queries][Queries]] @@ -82,6 +83,29 @@ More examples are available in [[examples.org]]. (not (children (todo))))) #+END_SRC +* Installation +:PROPERTIES: +:TOC: ignore-children +:END: + +The package may be installed directly from [[https://melpa.org/#/org-ql][MELPA]] or with other tools like [[https://framagit.org/steckerhalter/quelpa][Quelpa]]. + +After installation. you can use commands like ~org-ql-search~ immediately. + +To use the functions and macros in your own Elisp code, load the libraries ~org-ql~ and/or ~org-ql-agenda~ with e.g. ~(require 'org-ql)~. + +** Quelpa + +Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: + +1. Install [[https://framagit.org/steckerhalter/quelpa-use-package#installation][quelpa-use-package]] (which can be installed directly from MELPA). +2. Add this form to your init file: + +#+BEGIN_SRC elisp + (use-package org-ql + :quelpa (org-ql :fetcher github :repo "alphapapa/org-ql")) +#+END_SRC + * Usage The functionality provided may be grouped by: From 62fbd6123c9d7d6d10942984d65c27350e3ddf3c Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 19:35:25 -0500 Subject: [PATCH 282/970] Add: (org-ql-agenda, org-ql-search) :title argument --- README.org | 14 ++++++++++---- org-ql-agenda.el | 33 +++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/README.org b/README.org index ad78156..d33bd47 100644 --- a/README.org +++ b/README.org @@ -77,10 +77,11 @@ More examples are available in [[examples.org]]. ;; Show a "stuck projects" view: tasks that are not done and have only ;; non-task children. - (org-ql-agenda (org-agenda-files) - (and (todo) - (children) - (not (children (todo))))) + (org-ql-search (org-agenda-files) + '(and (todo) + (children) + (not (children (todo)))) + :title "Stuck Projects") #+END_SRC * Installation @@ -238,6 +239,7 @@ This macro is like ~org-ql~, but it presents matching entries in an Agenda-like (deadline <=) (scheduled <= today)) (not (done))) + :title "My Agenda View" ;; The `org-super-agenda-groups' setting is used automatically when set, or it ;; may be overriden by specifying it here: :super-groups ((:name "Bills" @@ -255,6 +257,9 @@ This macro is like ~org-ql~, but it presents matching entries in an Agenda-like (:priority "C" :order 2))) #+END_SRC +*************** TODO Update screenshot (doesn't show title) :noexport: +*************** END + Which presents this buffer: [[images/screenshot.png]] @@ -407,6 +412,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 8b71892..bb1a7af 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -65,6 +65,7 @@ (defvar org-ql-sort) (defvar org-ql-narrow) (defvar org-ql-super-groups) +(defvar org-ql-title) ;;;; Macros @@ -93,12 +94,13 @@ SUPER-GROUPS is used to bind variable `org-super-agenda-groups', which see. If t, the existing value of `org-super-agenda-groups' is used, rather than binding it locally." (declare (indent defun) - (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer super-groups) nil)) + (advertised-calling-convention (files-or-query &optional query &key sort narrow buffer super-groups title) nil)) (cl-macrolet ((set-keyword-args (args) `(setq sort (plist-get ,args :sort) narrow (plist-get ,args :narrow) buffer (plist-get ,args :buffer) - super-groups (plist-get ,args :super-groups)))) + super-groups (plist-get ,args :super-groups) + title (plist-get ,args :title)))) (let ((files '(org-agenda-files)) query sort narrow buffer super-groups) ;; Parse args manually (so we can leave FILES nil for a default argument). @@ -130,7 +132,8 @@ is used, rather than binding it locally." :sort ',sort :buffer ,buffer :narrow ,narrow - :super-groups ',super-groups)))) + :super-groups ',super-groups + :title ,title)))) ;;;; Commands @@ -138,7 +141,7 @@ is used, rather than binding it locally." ;; it uses `org-ql-agenda--agenda'. Maybe this could be better organized. ;;;###autoload -(cl-defun org-ql-search (buffers-files query &key narrow groups sort) +(cl-defun org-ql-search (buffers-files query &key narrow groups sort title) "Read QUERY and search with `org-ql'. Interactively, prompt for these variables: @@ -158,7 +161,9 @@ 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'. + +TITLE: An optional string displayed in the header." (declare (indent defun)) (interactive (list (pcase-exhaustive (completing-read "Buffers/Files: " (list 'buffer 'agenda 'all)) @@ -190,6 +195,7 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or :narrow narrow :sort sort :super-groups groups + :title title :buffer "*Org QL Search*")) (defun org-ql-search-refresh () @@ -200,6 +206,7 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or :sort org-ql-sort :narrow org-ql-narrow :super-groups org-ql-super-groups + :title org-ql-title :buffer (current-buffer))) ;;;; Functions @@ -207,7 +214,7 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the ;; headline-parser when they don't need it. -(cl-defun org-ql-agenda--agenda (buffers-files query &key entries sort buffer narrow super-groups) +(cl-defun org-ql-agenda--agenda (buffers-files query &key entries sort buffer narrow super-groups title) "FIXME: Docstring" (declare (indent defun)) (when (and super-groups (not org-super-agenda-mode)) @@ -241,7 +248,8 @@ SORT: One or a list of `org-ql' sorting functions, like `date' or (setq-local org-ql-sort sort) (setq-local org-ql-narrow narrow) (setq-local org-ql-super-groups super-groups) - (setq-local header-line-format (org-ql-agenda--header-line-format buffers-files query)) + (setq-local org-ql-title title) + (setq-local header-line-format (org-ql-agenda--header-line-format buffers-files query title)) ;; Clear buffer, insert entries, etc. (erase-buffer) (insert string) @@ -276,9 +284,13 @@ the `match' item in the custom command form." (defalias 'org-ql-block 'org-ql-agenda-block) -(defun org-ql-agenda--header-line-format (buffers-files query) +(defun org-ql-agenda--header-line-format (buffers-files query &optional title) "Return header-line-format for BUFFERS-FILES and QUERY." - (let* ((query-formatted (format "%S" query)) + (let* ((title (if title + (concat (propertize "View: " 'face 'org-agenda-structure) + title " ") + "")) + (query-formatted (format "%S" query)) (query-formatted (propertize (org-ql-agenda--font-lock-string 'emacs-lisp-mode query-formatted) 'help-echo query-formatted)) (query-width (length query-formatted)) @@ -291,7 +303,8 @@ the `match' item in the custom command form." (org-ql-agenda--font-lock-string 'emacs-lisp-mode) (s-truncate available-width)) 'help-echo buffers-files-formatted))) - (concat (propertize "Query: " 'face 'org-agenda-structure) + (concat title + (propertize "Query: " 'face 'org-agenda-structure) query-formatted " " (propertize "In: " 'face 'org-agenda-structure) buffers-files-formatted))) From 94d499bcf3ecf2897999e47c417eb2ce79536d19 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 19:37:21 -0500 Subject: [PATCH 283/970] Meta: Update description --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index f5bcebf..0f10702 100644 --- a/org-ql.el +++ b/org-ql.el @@ -1,4 +1,4 @@ -;;; org-ql.el --- Query language for Org buffers -*- lexical-binding: t; -*- +;;; org-ql.el --- Org Query Language, search command, and agenda-like view -*- lexical-binding: t; -*- ;; Author: Adam Porter ;; Url: https://github.com/alphapapa/org-ql From df8a155b14b84c2a6d2864dac30ef8c3a8e47189 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 19:38:37 -0500 Subject: [PATCH 284/970] Tidy: Indentation in example --- examples.org | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples.org b/examples.org index 316543d..233bd1c 100644 --- a/examples.org +++ b/examples.org @@ -5,8 +5,8 @@ #+BEGIN_SRC elisp (cl-defun org-ql-agenda-last-days (days &optional (type 'ts)) "Show entries from previous DAYS days with timestamps of TYPE. - TYPE may be `ts', `ts-active', `ts-inactive', `clocked', - `closed', `deadline', `planning', or `scheduled'." + TYPE may be `ts', `ts-active', `ts-inactive', `clocked', + `closed', `deadline', `planning', or `scheduled'." (interactive (list (read-number "Days: ") (->> '(ts ts-active ts-inactive clocked closed deadline planning scheduled) (completing-read "Timestamp type: ") From aea37ea1c104db3dc462ac8d95fe39efa5f6076a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:10:42 -0500 Subject: [PATCH 285/970] Docs: Add org-ql-view example --- examples.org | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/examples.org b/examples.org index 233bd1c..e2de499 100644 --- a/examples.org +++ b/examples.org @@ -1,5 +1,32 @@ * Examples +** Stored views command + +This defines a simple list of stored views and a command to easily access them with completion, which may be more convenient than defining a command for each view. + +#+BEGIN_SRC elisp + (defun org-ql-view (&optional view) + "Choose and display a stored `org-ql' view." + (interactive (list (completing-read "View: " (mapcar #'car org-ql-views)))) + (funcall (alist-get view org-ql-views nil nil #'string=))) + + (setq org-ql-views + (list (cons "Stuck Projects" (lambda () + (org-ql-agenda (org-agenda-files) + (and (todo) + (not (todo "TO-WATCH" "TO-READ" "MAYBE" "SOMEDAY")) + (children) + (not (children (todo))) + (not (habit))) + :title "Stuck Projects" + :sort (priority date) + :super-groups ((:name "Home" :tag "home") + (:tag ("Emacs" "computer") :order 100) + (:auto-parent t) + (:todo "WAITING") + (:auto-category t))))))) +#+END_SRC + ** Show entries with timestamps in the last N days #+BEGIN_SRC elisp @@ -28,7 +55,6 @@ ;; Show entries closed in last 7 days: (org-ql-agenda-last-days 30 'closed) #+END_SRC - ** Listing bills coming due This uses the example in the readme file, but maps across the elements returned by ~org-ql~ to present a simple list of titles and deadlines. From ae8b0c740c854d1e989d6900b35d89817029a4e9 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:11:58 -0500 Subject: [PATCH 286/970] Change: (ts) Use ts-in --- org-ql.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 0f10702..077c6ed 100644 --- a/org-ql.el +++ b/org-ql.el @@ -922,8 +922,7 @@ match inactive ones, or `both' / nil to match both types." (save-excursion (let ((end-pos (org-entry-end-position))) (cond ((not (or from to)) (re-search-forward regexp end-pos t)) - ((and from to) (test-timestamps (and (ts<= from next-ts) - (ts<= next-ts to)))) + ((and from to) (test-timestamps (ts-in from to next-ts))) (from (test-timestamps (ts<= from next-ts))) (to (test-timestamps (ts<= next-ts to)))))))) From 4a9379c83e23eb269eb301c8d72c9ed7fa0a879d Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:27:13 -0500 Subject: [PATCH 287/970] Comment: Correct comments --- org-ql.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/org-ql.el b/org-ql.el index 077c6ed..886f162 100644 --- a/org-ql.el +++ b/org-ql.el @@ -518,7 +518,7 @@ replace the clause with a preamble." "Return results for ARGS and current buffer using cache." ;; MAYBE: Timeout cached queries. Probably not necessarily since they will be removed when a ;; buffer is closed, or when a query is run after modifying a buffer. - ;; FIXME: Narrowed queries should conflict in the cache, because the region is not + ;; FIXME: Narrowed queries will probably conflict in the cache, because the region is not ;; stored. We should either not cache narrow queries, or store the region with it. (-let (((&plist :query query :action action :narrow narrow) args)) (if-let* ((buffer-cache (gethash (current-buffer) org-ql-cache)) @@ -909,7 +909,7 @@ parseable by `parse-time-string' which may omit the time value. TYPE may be `active' to match active timestamps, `inactive' to match inactive ones, or `both' / nil to match both types." ;; TODO: DRY this with the clocked predicate. - ;; NOTE: FROM and TO are actually expected to be Unix timestamps. The docstring is written + ;; NOTE: FROM and TO are actually expected to be `ts' structs. 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 () From eb38cf6b06514c051a6375f4217c08334323def1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:28:20 -0500 Subject: [PATCH 288/970] Comment: Clarify --- org-ql.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql.el b/org-ql.el index 886f162..57e31ba 100644 --- a/org-ql.el +++ b/org-ql.el @@ -577,7 +577,7 @@ If NARROW is non-nil, buffer will not be widened." ;; searches a buffer without headings, he might be confused. (message "org-ql: No headings in buffer: %s" (current-buffer))) nil) - ;; `cl-loop' makes this double-while much clearer than the expanded form. + ;; Find matching entries. (cond (preamble-re (cl-loop while (re-search-forward preamble-re nil t) do (outline-back-to-heading 'invisible-ok) when (funcall predicate) From 317a460c1df4281528140eaf267527d92384a0be Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:29:05 -0500 Subject: [PATCH 289/970] Tidy: (org-ql--parse-time-string) Remove Unused now. It served well. --- org-ql.el | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/org-ql.el b/org-ql.el index 57e31ba..9c5cfc7 100644 --- a/org-ql.el +++ b/org-ql.el @@ -623,25 +623,6 @@ Or, when possible, fix the problem." (org-ql--sanity-check-form (cdr elem))) else do (check elem)))) -(defun org-ql--parse-time-string (s &optional end) - "Return Unix timestamp by parsing timestamp string S. -Calls `parse-time-string' and fills in nil second, minute, and -hour values, then calls `float-time'. When END is non-nil, sets -empty time values to 23:59:59; otherwise, to 00:00:00." - ;; TODO: Also accept Unix timestamps. - (cl-macrolet ((fill-with (place value) - `(unless (nth ,place parsed-time) - (setf (nth ,place parsed-time) ,value)))) - (let ((parsed-time (parse-time-string s))) - (pcase end - ('nil (fill-with 0 0) - (fill-with 1 0) - (fill-with 2 0)) - (_ (fill-with 0 59) - (fill-with 1 59) - (fill-with 2 23))) - (float-time (apply #'encode-time parsed-time))))) - ;;;;; Predicates (org-ql--defpred children (query) From b256fa6a78e30c50949db5ecc510e218b4f8ae5e Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 21:33:54 -0500 Subject: [PATCH 290/970] Change: (org-ql-agenda--header-line-format) Spacing A bit more compact. --- org-ql-agenda.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index bb1a7af..84b5ef4 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -287,7 +287,7 @@ the `match' item in the custom command form." (defun org-ql-agenda--header-line-format (buffers-files query &optional title) "Return header-line-format for BUFFERS-FILES and QUERY." (let* ((title (if title - (concat (propertize "View: " 'face 'org-agenda-structure) + (concat (propertize "View:" 'face 'org-agenda-structure) title " ") "")) (query-formatted (format "%S" query)) @@ -304,9 +304,9 @@ the `match' item in the custom command form." (s-truncate available-width)) 'help-echo buffers-files-formatted))) (concat title - (propertize "Query: " 'face 'org-agenda-structure) + (propertize "Query:" 'face 'org-agenda-structure) query-formatted " " - (propertize "In: " 'face 'org-agenda-structure) + (propertize "In:" 'face 'org-agenda-structure) buffers-files-formatted))) (defun org-ql-agenda--font-lock-string (mode s) From 7cb80552bac43201b4fd6f338893694868f75876 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 22:19:47 -0500 Subject: [PATCH 291/970] Docs: Update/add examples --- examples.org | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/examples.org b/examples.org index e2de499..f48f8bb 100644 --- a/examples.org +++ b/examples.org @@ -1,6 +1,15 @@ -* Examples +#+TITLE: org-ql examples -** Stored views command +* Contents +:PROPERTIES: +:TOC: this +:END: + - [[#stored-views-command][Stored views command]] + - [[#show-entries-with-timestamps-in-the-last-n-days][Show entries with timestamps in the last N days]] + - [[#stuck-projects-block-agenda][Stuck projects block agenda]] + - [[#listing-bills-coming-due][Listing bills coming due]] + +* Stored views command This defines a simple list of stored views and a command to easily access them with completion, which may be more convenient than defining a command for each view. @@ -27,7 +36,7 @@ This defines a simple list of stored views and a command to easily access them w (:auto-category t))))))) #+END_SRC -** Show entries with timestamps in the last N days +* Show entries with timestamps in the last N days #+BEGIN_SRC elisp (cl-defun org-ql-agenda-last-days (days &optional (type 'ts)) @@ -55,7 +64,28 @@ This defines a simple list of stored views and a command to easily access them w ;; Show entries closed in last 7 days: (org-ql-agenda-last-days 30 'closed) #+END_SRC -** Listing bills coming due + +* Stuck projects block agenda + +Reddit user =emptymatrix= [[https://www.reddit.com/r/emacs/comments/cnrt2d/orgqlblock_integrates_orgql_into_org_agenda/ewtqez8/][shared]] this example of replacing a traditional =org-stuck-projects= view like: + +#+BEGIN_SRC elisp + (setq org-stuck-projects + '("+@project/-DONE" ("NEXT") nil "SCHEDULED:")) +#+END_SRC + +With this =org-ql-block= agenda view, like: + +#+BEGIN_SRC elisp + (setq org-agenda-custom-commands + '(("s" "Stuck Projects" + ((org-ql-block '(and (tags "@project") + (not (done)) + (not (descendants (todo "NEXT"))) + (not (descendants (scheduled))))))))) +#+END_SRC + +* Listing bills coming due This uses the example in the readme file, but maps across the elements returned by ~org-ql~ to present a simple list of titles and deadlines. @@ -72,3 +102,15 @@ This uses the example in the readme file, but maps across the elements returned #+END_SRC This could also be put in a script, which could use desktop notifications to remind of bills coming due: [[examples/org-bills-due.el][org-bills-due.el]]. + +* COMMENT Code :noexport: +:PROPERTIES: +:TOC: ignore +:END: + +** File-local variables + +# Local Variables: +# eval: (require 'org-make-toc) +# before-save-hook: org-make-toc +# End: From 9c45a020c18c8382f014244afcfdf884f2136f90 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 22:23:23 -0500 Subject: [PATCH 292/970] Docs: Update example --- examples.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples.org b/examples.org index f48f8bb..d63e222 100644 --- a/examples.org +++ b/examples.org @@ -53,7 +53,7 @@ This defines a simple list of stored views and a command to easily access them w ;; Formatting isn't required, but it looks better in the header than a struct. ts-format))) (org-ql-search (org-agenda-files) - `(,type :from ,from :to ,(ts-now))))) + `(,type :from ,from :to ,(ts-format (ts-now)))))) ;; Show entries with any timestamp from last 7 days: (org-ql-agenda-last-days 7) From 0a692077596cbfb2c8bdeb50dbd2d7f12b9c16d4 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 22:35:06 -0500 Subject: [PATCH 293/970] Add: (org-ql-search) Offer global groups --- README.org | 1 + org-ql-agenda.el | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.org b/README.org index d33bd47..1d6622d 100644 --- a/README.org +++ b/README.org @@ -413,6 +413,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 84b5ef4..54644a1 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -177,8 +177,10 @@ TITLE: An optional string displayed in the header." :narrow (eq current-prefix-arg '(4)) :groups (pcase (completing-read "Group by: " (cons "Don't group" + "Global groups" (cl-loop for type in org-super-agenda-auto-selector-keywords collect (substring (symbol-name type) 6)))) + ("Global groups" org-super-agenda-groups) ("Don't group" nil) (property (list (list (intern (concat ":auto-" property)))))) :sort (pcase (completing-read "Sort by: " From 31405d91ccd6233686b64ec36e74f10fe453d9bd Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Tue, 13 Aug 2019 22:35:53 -0500 Subject: [PATCH 294/970] Docs: Improve example I should add this command to the package, this is really useful. --- examples.org | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/examples.org b/examples.org index d63e222..1855094 100644 --- a/examples.org +++ b/examples.org @@ -5,7 +5,7 @@ :TOC: this :END: - [[#stored-views-command][Stored views command]] - - [[#show-entries-with-timestamps-in-the-last-n-days][Show entries with timestamps in the last N days]] + - [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]] - [[#stuck-projects-block-agenda][Stuck projects block agenda]] - [[#listing-bills-coming-due][Listing bills coming due]] @@ -36,11 +36,11 @@ This defines a simple list of stored views and a command to easily access them w (:auto-category t))))))) #+END_SRC -* Show entries with timestamps in the last N days +* Show entries with recent timestamps #+BEGIN_SRC elisp - (cl-defun org-ql-agenda-last-days (days &optional (type 'ts)) - "Show entries from previous DAYS days with timestamps of TYPE. + (cl-defun org-ql-agenda-recent-items (days &optional (type 'ts)) + "Show items from previous DAYS days with timestamps of TYPE. TYPE may be `ts', `ts-active', `ts-inactive', `clocked', `closed', `deadline', `planning', or `scheduled'." (interactive (list (read-number "Days: ") @@ -53,16 +53,22 @@ This defines a simple list of stored views and a command to easily access them w ;; Formatting isn't required, but it looks better in the header than a struct. ts-format))) (org-ql-search (org-agenda-files) - `(,type :from ,from :to ,(ts-format (ts-now)))))) + `(,type :from ,from :to ,(ts-format (ts-now))) + :title "Recent items" + :sort '(date priority todo) + :groups '((:todo "DONE") + (:category "log" :tag "log") + (:auto-parent t) + (:auto-todo t))))) ;; Show entries with any timestamp from last 7 days: - (org-ql-agenda-last-days 7) + (org-ql-agenda-recent-items 7) ;; Show entries clocked in last 7 days: - (org-ql-agenda-last-days 30 'clocked) + (org-ql-agenda-recent-items 30 'clocked) ;; Show entries closed in last 7 days: - (org-ql-agenda-last-days 30 'closed) + (org-ql-agenda-recent-items 30 'closed) #+END_SRC * Stuck projects block agenda From 2d6a8fbe66cb4321e45580de72d2d724a78b4848 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Wed, 14 Aug 2019 13:10:17 -0500 Subject: [PATCH 295/970] Docs: Fix punctuation --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 1d6622d..dd7b76e 100644 --- a/README.org +++ b/README.org @@ -91,7 +91,7 @@ More examples are available in [[examples.org]]. The package may be installed directly from [[https://melpa.org/#/org-ql][MELPA]] or with other tools like [[https://framagit.org/steckerhalter/quelpa][Quelpa]]. -After installation. you can use commands like ~org-ql-search~ immediately. +After installation, you can use commands like ~org-ql-search~ immediately. To use the functions and macros in your own Elisp code, load the libraries ~org-ql~ and/or ~org-ql-agenda~ with e.g. ~(require 'org-ql)~. From a71e49b70adc794feac91d2b410979aee9093c50 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 00:56:22 -0500 Subject: [PATCH 296/970] Notes: Remove done task --- notes.org | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/notes.org b/notes.org index 9b3f2d1..13e936d 100644 --- a/notes.org +++ b/notes.org @@ -51,29 +51,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 [#B] Implied string literal regexp selector - -As mentioned [[https://www.reddit.com/r/emacs/comments/c8e0zp/my_gnu_hyperbole_vision_quest_odyssey_two/esmtqow/][here]]: - -#+BEGIN_QUOTE markdown -> Third – The “StringFind” search tool seems to be busted currently, but it’s pretty killer when it works. Basically, it lets you do boolean searches through records, so entering: - -> `(and sonnet italian (not petrarch))` - -`helm-org-rifle` provides this, e.g. the equivalent query would be: - -`sonnet italian !petrarch` - -`org-ql` also provides a lispy way to do this, e.g.: - - (org-ql "poetry.org" - (and (regexp "sonnet") - (regexp "italian") - (not (regexp "petrarch")))) - -It is more verbose because of the explicit `regexp` selector, but it would be easy to add an implied string literal selector. Putting that on the to-do list now... ;) -#+END_QUOTE - ** TODO [#A] Tools for saving queries and accessing them *** TODO Save query from ql-agenda buffer From e5791289c30184519be04a49d3c3420646b81285 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 00:57:06 -0500 Subject: [PATCH 297/970] Notes: Fix macro --- notes.org | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/notes.org b/notes.org index 13e936d..75b56c7 100644 --- a/notes.org +++ b/notes.org @@ -104,9 +104,9 @@ This would require processing the predicate to pull out matchers that can be don `(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-query ,file - ',query - :action (lambda () (org-get-heading t t))))))) + :forms ((,(prin1-to-string query) (org-ql-select,file + ',query + :action (lambda () (org-get-heading t t))))))) #+END_SRC #+BEGIN_SRC elisp From 2831e940eb380e28377ae1538d4babc14feb74ca Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 01:00:28 -0500 Subject: [PATCH 298/970] Notes: Update code --- notes.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notes.org b/notes.org index 75b56c7..3e3e329 100644 --- a/notes.org +++ b/notes.org @@ -429,7 +429,7 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled #+BEGIN_SRC elisp (org-super-agenda--test-with-org-today-date "2017-07-08 00:00" - (org-agenda-ng "~/src/emacs/org-super-agenda/test/test.org" + (org-ql "~/src/emacs/org-super-agenda/test/test.org" (and (or (date = today) (deadline <=) (scheduled <= today)) From c2022b61685e847f1f021192923fde7012e78023 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 01:00:40 -0500 Subject: [PATCH 299/970] Notes: Add WIP Helm stuff --- notes.org | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/notes.org b/notes.org index 3e3e329..5aef795 100644 --- a/notes.org +++ b/notes.org @@ -436,6 +436,46 @@ Also, maybe instead of having a single =date= selector, I should have =scheduled (not (done))))) #+END_SRC +** Helm + +#+BEGIN_SRC elisp + (defun helm-org-ql-heading () + (let* ((path (mapconcat 'identity + (nreverse (org-split-string (org-format-outline-path (org-get-outline-path) + 1000 nil "") + "")) + org-sticky-header-outline-path-reversed-separator)) + (s (concat (org-sticky-header--get-prefix) + (org-get-heading) + org-sticky-header-outline-path-reversed-separator + path))) + (remove-list-of-text-properties 0 (length s) '(line-prefix) s) + (s-trim (if (> (length s) (window-width)) + (concat (substring s 0 (- (window-width) 2)) + "..") + s)))) + + (defun helm-org-ql-next () + (interactive) + (helm :sources (list (helm-build-sync-source "helm-org-ql" + ;; :after-init-hook helm-org-rifle-after-init-hook + :candidates (lambda () + (or (when-let* ((items (org-ql-select (org-agenda-files) + '(todo "NEXT") + :action 'element-with-markers + :sort '(priority date)))) + (--map (let* ((marker (org-element-property :org-marker it))) + (org-with-point-at marker + (cons (helm-org-ql-heading) marker))) + items)) + (list "NONE"))) + :match 'identity + :multiline nil + :volatile t + :action 'helm-org-rifle-actions + :keymap helm-org-rifle-map)))) +#+END_SRC + * Profiling ** Preambles From c3b1c0e1402edbd7d2739837ce16b78eca93fbe5 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 01:04:22 -0500 Subject: [PATCH 300/970] Notes: Add idea --- notes.org | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/notes.org b/notes.org index 5aef795..f80dd95 100644 --- a/notes.org +++ b/notes.org @@ -8,6 +8,15 @@ Would probably be useful to have a default sort option. +** TODO [#A] Outline path in buffers-files arg + +e.g. + +#+BEGIN_SRC elisp + (org-ql (olp "~/org/inbox.org" "Emacs" "Ideas") + (todo "NEXT")) +#+END_SRC + ** TODO ~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: From b2d54e488967dd821e8f970ff56832e0f817a4d7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 01:06:06 -0500 Subject: [PATCH 301/970] Notes: Update --- notes.org | 299 ++++++++++++++++++++++++++---------------------------- 1 file changed, 143 insertions(+), 156 deletions(-) diff --git a/notes.org b/notes.org index f80dd95..5aab19d 100644 --- a/notes.org +++ b/notes.org @@ -2,12 +2,6 @@ * Tasks -** TODO Update commentary - -** TODO [#B] Default sort - -Would probably be useful to have a default sort option. - ** TODO [#A] Outline path in buffers-files arg e.g. @@ -17,6 +11,59 @@ e.g. (todo "NEXT")) #+END_SRC +** TODO [#A] Tools for saving queries and accessing them + ++ Added example to =examples.org=. + +*** TODO Save query from ql-agenda buffer + +*** TODO 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 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 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 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 + +** TODO 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 ~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: @@ -60,156 +107,7 @@ 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 [#A] Tools for saving queries and accessing them - -*** TODO Save query from ql-agenda buffer - -*** TODO 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 [#A] Store query for refreshing ql-agenda buffer - -** 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! - -** TODO 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 [#A] Publish to MELPA - -** TODO Add more sorters? - -+ [ ] =category= -+ [ ] Any date :: e.g. it would search for timestamps (active/inactive?) anywhere in an entry - -** TODO Document matchers/selectors/predicates - -And maybe pick a single name for them... - -+ =deadline= :: Be sure to explain how it works with regard to the implied date and =today=. -+ =date=, =scheduled= :: No implied date, but supports =today=. - -** TODO 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 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 - -** MAYBE Date predicate that searches entire entry - -Because the existing ones only search the special date property line. +** TODO Update commentary ** MAYBE Fancier searching for inherited tags @@ -332,6 +230,95 @@ Virtually indistinguishable. Going to try moving the =byte-compile= call from t Doesn't seem to make any difference. +** 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: From 6cd934114631f7b614b652a30d6cfaca9adfc264 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 17:47:39 -0500 Subject: [PATCH 302/970] Fix: (org-ql-agenda--header-line-format) Available width Could cause an error with very long queries. --- org-ql-agenda.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 54644a1..be44798 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -296,10 +296,10 @@ the `match' item in the custom command form." (query-formatted (propertize (org-ql-agenda--font-lock-string 'emacs-lisp-mode query-formatted) 'help-echo query-formatted)) (query-width (length query-formatted)) - (available-width (- (window-width) - (length "In: ") - (length "Query: ") - query-width 4)) + (available-width (max 0 (- (window-width) + (length "In: ") + (length "Query: ") + query-width 4))) (buffers-files-formatted (format "%S" buffers-files)) (buffers-files-formatted (propertize (->> buffers-files-formatted (org-ql-agenda--font-lock-string 'emacs-lisp-mode) From da711ebb35e928f13ba83494984be928825eebb6 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 23:34:23 -0500 Subject: [PATCH 303/970] Fix: (org-ql-search) Interactive completion --- org-ql-agenda.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index be44798..972f59e 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -176,10 +176,10 @@ TITLE: An optional string displayed in the header." (read-minibuffer "Query: ") :narrow (eq current-prefix-arg '(4)) :groups (pcase (completing-read "Group by: " - (cons "Don't group" - "Global groups" - (cl-loop for type in org-super-agenda-auto-selector-keywords - collect (substring (symbol-name type) 6)))) + (append (list "Don't group" + "Global groups") + (cl-loop for type in org-super-agenda-auto-selector-keywords + collect (substring (symbol-name type) 6)))) ("Global groups" org-super-agenda-groups) ("Don't group" nil) (property (list (list (intern (concat ":auto-" property)))))) From 27e343700d6e3a2fec9ba9250617fac4d200c8ca Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 15 Aug 2019 23:35:47 -0500 Subject: [PATCH 304/970] Notes: Add --- notes.org | 2 ++ 1 file changed, 2 insertions(+) diff --git a/notes.org b/notes.org index 5aab19d..b7d0b8a 100644 --- a/notes.org +++ b/notes.org @@ -11,6 +11,8 @@ e.g. (todo "NEXT")) #+END_SRC +Also, should support an ~id~ one. + ** TODO [#A] Tools for saving queries and accessing them + Added example to =examples.org=. From 62878f5d9f28ea089034e744e400a3f333bbb035 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 11:47:04 -0500 Subject: [PATCH 305/970] Fix: Free variable warning --- org-ql-agenda.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 972f59e..ba24e1f 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -102,7 +102,7 @@ is used, rather than binding it locally." super-groups (plist-get ,args :super-groups) title (plist-get ,args :title)))) (let ((files '(org-agenda-files)) - query sort narrow buffer super-groups) + query sort narrow buffer super-groups title) ;; Parse args manually (so we can leave FILES nil for a default argument). ;; TODO: DRY this and org-ql, I think. (pcase args From 6aeb3030c6777822d73cb1f1b4e8f60c48b0636a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 12:14:36 -0500 Subject: [PATCH 306/970] Add: Customization group --- README.org | 1 + org-ql-agenda.el | 3 ++- org-ql.el | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/README.org b/README.org index dd7b76e..f570303 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 + 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~. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index ba24e1f..7a37646 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -52,7 +52,8 @@ (defface org-ql-agenda-due-date '((t (:slant italic :weight bold))) - "Face for due dates in `org-ql-agenda' views.") + "Face for due dates in `org-ql-agenda' views." + :group 'org-ql) ;;;; Variables diff --git a/org-ql.el b/org-ql.el index 9c5cfc7..bb9e392 100644 --- a/org-ql.el +++ b/org-ql.el @@ -95,6 +95,13 @@ hash table, keyed by arguments passed to "Plist of predicates, their corresponding functions, and their docstrings. This list should not contain any duplicates.") +;;;; Customization + +(defgroup org-ql nil + "Customization for `org-ql'." + :group 'org + :link '(url-link "https://github.com/alphapapa/org-ql")) + ;;;; Macros (cl-defmacro org-ql--defpred (name args docstring &rest body) From 429c31363445bd8237eb0e99b64e21a8b9da11f7 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 12:27:30 -0500 Subject: [PATCH 307/970] Docs: Organize commands --- README.org | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index f570303..f6044eb 100644 --- a/README.org +++ b/README.org @@ -111,13 +111,24 @@ Installing with [[https://framagit.org/steckerhalter/quelpa][Quelpa]] is easy: The functionality provided may be grouped by: -+ Interactive commands :: ~org-ql-search~ -+ Non-interactive functions and macros :: ~org-ql~ (macro), ~org-ql-select~ (function), ~org-ql-query~ (function), ~org-ql-block~ (agenda function), and ~org-ql-agenda~ (macro) ++ *Interactive commands:* ~org-ql-search~, ~org-ql-view~. ++ *Non-interactive functions and macros:* + - ~org-ql~ (macro) + - ~org-ql-select~ (function) + - ~org-ql-query~ (function) + - ~org-ql-agenda~ (macro) + - ~org-ql-block~ (agenda function) Alternatively, they may be grouped by: -+ Showing an agenda-like view :: ~org-ql-search~ (command), ~org-ql-block~ (agenda function), and ~org-ql-agenda~ (macro) -+ Returning a list of matches or acting on them :: ~org-ql~ (macro), ~org-ql-select~ (function), and ~org-ql-query~ (function) ++ *Showing an agenda-like view:* + - ~org-ql-search~ (command) + - ~org-ql-block~ (agenda function) + - ~org-ql-agenda~ (macro) ++ *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. From ae3ec62e3cddee4db3a2423debea5da15fc425ac Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 12:29:20 -0500 Subject: [PATCH 308/970] Add: org-ql-view-map --- README.org | 4 +++- org-ql-agenda.el | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.org b/README.org index f6044eb..fe8f963 100644 --- a/README.org +++ b/README.org @@ -155,7 +155,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~. -Press =g= to refresh the results buffer. +*Bindings:* ++ =g=: Refresh results. [[images/org-ql-search.gif]] @@ -426,6 +427,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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~. ++ Variable ~org-ql-view-map~, active in view buffers displayed by ~org-ql-search~, ~org-ql-agenda~, and ~org-ql-view~. *Changed* + Function ~org-ql-query~ renamed to ~org-ql-select~. ~org-ql-query~ now refers to a new function. diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 7a37646..6ac4dd4 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -60,6 +60,14 @@ (defvar org-ql-agenda-buffer-name "*Org-QL-Agenda*" "Name of default `org-ql-agenda' buffer.") +(defvar org-ql-view-map + (let ((map (copy-keymap org-agenda-mode-map))) + (define-key map "g" #'org-ql-search-refresh) + (define-key map (kbd "C-x C-s") #'org-ql-search-save) + map) + "Keymap for `org-ql-agenda', `org-ql-search', and `org-ql-views' views. +Based on `org-agenda-mode-map'.") + ;; For refreshing results buffers. (defvar org-ql-buffers-files) (defvar org-ql-query) @@ -240,11 +248,9 @@ TITLE: An optional string displayed in the header." (string (org-ql-agenda--buffer buffer)) (null (org-ql-agenda--buffer buffer)) (buffer buffer))) - (map (copy-keymap org-agenda-mode-map)) (inhibit-read-only t)) - (define-key map "g" #'org-ql-search-refresh) (with-current-buffer buffer - (use-local-map map) + (use-local-map org-ql-view-map) ;; Prepare buffer, saving data for refreshing. (setq-local org-ql-buffers-files buffers-files) (setq-local org-ql-query query) From be92d531ecbc85d38777e82d7f2e80f4e6150070 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 12:30:37 -0500 Subject: [PATCH 309/970] Add: org-ql-view, org-ql-views, org-ql-search-save --- README.org | 7 ++++++ examples.org | 28 ---------------------- org-ql-agenda.el | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 28 deletions(-) diff --git a/README.org b/README.org index fe8f963..9a39fdf 100644 --- a/README.org +++ b/README.org @@ -123,6 +123,7 @@ Alternatively, they may be grouped by: + *Showing an agenda-like view:* - ~org-ql-search~ (command) + - ~org-ql-view~ (command) - ~org-ql-block~ (agenda function) - ~org-ql-agenda~ (macro) + *Returning a list of matches or acting on them:* @@ -157,6 +158,7 @@ Read ~QUERY~ and search with ~org-ql~. Interactively, prompt for these variable *Bindings:* + =g=: Refresh results. ++ =C-x C-s=: Save query to variable ~org-ql-views~ (accessible with command ~org-ql-view~). [[images/org-ql-search.gif]] @@ -164,6 +166,10 @@ Here's an example of using it to generate an agenda-like view for certain files [[images/org-ql-search-snippet.png]] +*** org-ql-view + +Choose and display a view stored in ~org-ql-views~. + ** Queries A 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. @@ -427,6 +433,7 @@ Expands into a call to ~org-ql-select~ with the same arguments. For convenience + 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~. *Changed* diff --git a/examples.org b/examples.org index 1855094..759ea3e 100644 --- a/examples.org +++ b/examples.org @@ -4,38 +4,10 @@ :PROPERTIES: :TOC: this :END: - - [[#stored-views-command][Stored views command]] - [[#show-entries-with-recent-timestamps][Show entries with recent timestamps]] - [[#stuck-projects-block-agenda][Stuck projects block agenda]] - [[#listing-bills-coming-due][Listing bills coming due]] -* Stored views command - -This defines a simple list of stored views and a command to easily access them with completion, which may be more convenient than defining a command for each view. - -#+BEGIN_SRC elisp - (defun org-ql-view (&optional view) - "Choose and display a stored `org-ql' view." - (interactive (list (completing-read "View: " (mapcar #'car org-ql-views)))) - (funcall (alist-get view org-ql-views nil nil #'string=))) - - (setq org-ql-views - (list (cons "Stuck Projects" (lambda () - (org-ql-agenda (org-agenda-files) - (and (todo) - (not (todo "TO-WATCH" "TO-READ" "MAYBE" "SOMEDAY")) - (children) - (not (children (todo))) - (not (habit))) - :title "Stuck Projects" - :sort (priority date) - :super-groups ((:name "Home" :tag "home") - (:tag ("Emacs" "computer") :order 100) - (:auto-parent t) - (:todo "WAITING") - (:auto-category t))))))) -#+END_SRC - * Show entries with recent timestamps #+BEGIN_SRC elisp diff --git a/org-ql-agenda.el b/org-ql-agenda.el index 6ac4dd4..b62eeb2 100644 --- a/org-ql-agenda.el +++ b/org-ql-agenda.el @@ -27,6 +27,7 @@ ;;; Code: (require 'cl-lib) +(require 'map) (require 'org) (require 'org-element) (require 'org-agenda) @@ -76,6 +77,42 @@ Based on `org-agenda-mode-map'.") (defvar org-ql-super-groups) (defvar org-ql-title) +;;;; Customization + +(defcustom org-ql-views + (list (cons "Recent entries" (cl-function + (lambda (days &optional (type 'ts)) + (interactive (list (read-number "Days: ") + (->> '(ts ts-active ts-inactive clocked closed deadline planning scheduled) + (completing-read "Timestamp type: ") + intern))) + (let ((from (->> (ts-now) + (ts-adjust 'day (* -1 days)) + (ts-apply :hour 0 :minute 0 :second 0) + ;; Formatting isn't required, but it looks better in the header than a struct. + ts-format))) + (org-ql-search (org-agenda-files) + `(,type :from ,from :to ,(ts-format (ts-now))) + :title "Recent Entries" + :sort '(date priority todo) + :groups '((:todo "DONE") + (:auto-parent t) + (:auto-todo t))))))) + (cons "Stuck Projects" (lambda () + (interactive) + (org-ql-search (org-agenda-files) + '(and (todo) + (children) + (not (children (todo "NEXT")))) + :title "Stuck Projects" + :sort '(priority date))))) + "Alist of `org-ql-view' commands. +Each value should be a function that calls, +e.g. `org-ql-search' as desired." + :group 'org-ql + :type '(alist :key-type string + :value-type function)) + ;;;; Macros ;; FIXME: DRY these two macros. @@ -220,6 +257,31 @@ TITLE: An optional string displayed in the header." :title org-ql-title :buffer (current-buffer))) +(defun org-ql-search-save () + "Save current `org-ql-search' buffer to `org-ql-views'." + (interactive) + (let* ((name (read-string "Save view as: ")) + (buffers-files-sexp (cl-etypecase org-ql-buffers-files + (string org-ql-buffers-files) + (list `(list ,@org-ql-buffers-files)) + (null nil))) + (function `(lambda () + (interactive) + (org-ql-search ,buffers-files-sexp + ',org-ql-query + :sort ',org-ql-sort + :narrow ,org-ql-narrow + :groups ',org-ql-super-groups + :title ,name)))) + (map-put org-ql-views name function #'equal) + (customize-set-variable 'org-ql-views org-ql-views) + (customize-mark-to-save 'org-ql-views))) + +(defun org-ql-view (&optional view) + "Choose and display a view stored in `org-ql-views'." + (interactive (list (completing-read "View: " (mapcar #'car org-ql-views)))) + (call-interactively (alist-get view org-ql-views nil nil #'string=))) + ;;;; Functions ;; TODO: Move the action-fn down into --filter-buffer, so users can avoid calling the From 869ce69f1dba8d80c715193974e9c60261306852 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Fri, 16 Aug 2019 12:43:35 -0500 Subject: [PATCH 310/970] Docs: Bindings --- README.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.org b/README.org index 9a39fdf..dcb0b4a 100644 --- a/README.org +++ b/README.org @@ -156,7 +156,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:* +*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~). From 26a8c3d5dc745181e3169c0a8185028820177a85 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 18 Aug 2019 20:27:11 -0500 Subject: [PATCH 311/970] Tests: Add convenient comment --- tests/test-org-ql.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test-org-ql.el b/tests/test-org-ql.el index df4a917..21113b6 100644 --- a/tests/test-org-ql.el +++ b/tests/test-org-ql.el @@ -125,6 +125,8 @@ RESULTS should be a list of strings as returned by (substring-no-properties (org-get-heading t t t t)))) (setq test-buffer (find-file-noselect (concat default-directory "tests/data.org")) + ;; 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)) From 99a18dff2a20964a7575e73390aa39ab28b4cec1 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 18 Aug 2019 21:08:35 -0500 Subject: [PATCH 312/970] Comment: Add TODO --- org-ql.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org-ql.el b/org-ql.el index bb9e392..0535bb0 100644 --- a/org-ql.el +++ b/org-ql.el @@ -780,6 +780,9 @@ comparator, PRIORITY should be a priority string." ;;;;;; Timestamps +;; TODO: Remove the _on vars from these arg lists. I think they're not +;; necessary, or shouldn't be, since --pre-process-query should handle them. + (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 From ab3d1178b9ccf1bca4e157c6d88e97299a19648a Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Sun, 18 Aug 2019 21:28:06 -0500 Subject: [PATCH 313/970] Add: Call some ts-type predicates with a number/auto --- README.org | 26 ++++++++++------ examples.org | 33 +++++++++----------- examples/org-bills-due.el | 2 +- org-ql.el | 64 +++++++++++++++++++++++++++++++++++++++ tests/test-org-ql.el | 41 +++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 30 deletions(-) diff --git a/README.org b/README.org index dcb0b4a..9431fd7 100644 --- a/README.org +++ b/README.org @@ -44,16 +44,16 @@ More examples are available in [[examples.org]]. :action '(org-toggle-tag "Emacs" 'on)) ;; Return a list of bills coming due, searching all Org Agenda files, - ;; sorted by deadline. Deadlines are compared with - ;; `org-deadline-warning-days', which is implied by the plain `<=' in - ;; the `deadline' predicate. `org-ql-query' works like `org-ql-select' - ;; but offers arguments named like SQL queries. + ;; sorted by deadline. The `auto' argument to `deadline' means to match + ;; entries whose deadlines fall within `org-deadline-warning-days'. + ;; `org-ql-query' works like `org-ql-select' but offers arguments named + ;; like SQL queries. (org-ql-query :select #'org-get-heading :from (org-agenda-files) :where '(and (not (done)) (tags "bills") - (deadline <=)) + (deadline auto)) :order-by 'deadline) ;;=> ("TODO Electric bill" "TODO Water bill") @@ -205,17 +205,23 @@ Arguments are listed next to predicate names, where applicable. All of these selectors 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 ~ts~ structs, or strings parseable by ~parse-time-string~ which may omit the time value. -+ ~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. -+ ~deadline~ :: Return non-nil if current entry has deadline in given period. 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. + ~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~ :: Like ~ts~, but only matches active timestamps. + ~ts-a~ :: Like ~ts~, but only matches active timestamps. + ~ts-inactive~ :: Like ~ts~, but only matches inactive timestamps. + ~ts-i~ :: Like ~ts~, but only matches inactive timestamps. +The following selectors can also take a single argument, a number, which looks backward or forward a number of days. The number can also 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. + ** Functions / Macros :PROPERTIES: :TOC: ignore-children diff --git a/examples.org b/examples.org index 759ea3e..b90c9da 100644 --- a/examples.org +++ b/examples.org @@ -11,7 +11,7 @@ * Show entries with recent timestamps #+BEGIN_SRC elisp - (cl-defun org-ql-agenda-recent-items (days &optional (type 'ts)) + (cl-defun org-ql-view-recent-items (days &optional (type 'ts)) "Show items from previous DAYS days with timestamps of TYPE. TYPE may be `ts', `ts-active', `ts-inactive', `clocked', `closed', `deadline', `planning', or `scheduled'." @@ -19,28 +19,23 @@ (->> '(ts ts-active ts-inactive clocked closed deadline planning scheduled) (completing-read "Timestamp type: ") intern))) - (let ((from (->> (ts-now) - (ts-adjust 'day (* -1 days)) - (ts-apply :hour 0 :minute 0 :second 0) - ;; Formatting isn't required, but it looks better in the header than a struct. - ts-format))) - (org-ql-search (org-agenda-files) - `(,type :from ,from :to ,(ts-format (ts-now))) - :title "Recent items" - :sort '(date priority todo) - :groups '((:todo "DONE") - (:category "log" :tag "log") - (:auto-parent t) - (:auto-todo t))))) + (org-ql-search (org-agenda-files) + `(,type ,days) + :title "Recent items" + :sort '(date priority todo) + :groups '((:todo "DONE") + (:name "Log" :category "log" :tag "log") + (:auto-parent t) + (:auto-todo t)))) ;; Show entries with any timestamp from last 7 days: - (org-ql-agenda-recent-items 7) + (org-ql-view-recent-items 7) - ;; Show entries clocked in last 7 days: - (org-ql-agenda-recent-items 30 'clocked) + ;; Show entries clocked in last 30 days: + (org-ql-view-recent-items 30 'clocked) - ;; Show entries closed in last 7 days: - (org-ql-agenda-recent-items 30 'closed) + ;; Show entries closed in last 30 days: + (org-ql-view-recent-items 30 'closed) #+END_SRC * Stuck projects block agenda diff --git a/examples/org-bills-due.el b/examples/org-bills-due.el index 5c7261c..c544734 100644 --- a/examples/org-bills-due.el +++ b/examples/org-bills-due.el @@ -35,7 +35,7 @@ (-if-let* ((header "Bills due within 3 days") (items (org-ql "~/org/main.org" - (and (deadline <= (+ 3 today)) + (and (deadline 3) (tags "bills")) :action (org-get-heading 'no-tags 'no-todo))) (string (concat "

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