From 94f9e6f3031b32cf5e2149beca7074807235dcb0 Mon Sep 17 00:00:00 2001 From: Adam Porter Date: Thu, 17 Jun 2021 18:59:40 -0500 Subject: [PATCH] Add/Change: reverse sorter, and reverse sorting order This is a breaking change of sorts in that searches using multiple sorting methods will have to have the order of the sorters reversed to get the same result. Unfortunate, but I think it's worth it in the end, and this is pre-1.0, anyway. Fixes #143. --- README.org | 2 ++ examples.org | 4 ++-- org-ql-view.el | 14 +++++++------ org-ql.el | 34 ++++++++++++++++++++---------- org-ql.info | 57 ++++++++++++++++++++++++++++---------------------- 5 files changed, 67 insertions(+), 44 deletions(-) diff --git a/README.org b/README.org index 77875354..1ebfead1 100644 --- a/README.org +++ b/README.org @@ -529,8 +529,10 @@ Simple links may also be written manually in either sexp or non-sexp form, like: + Predicate ~effort~. + Predicate ~heading-regexp~, which matches regular expressions against heading text (alias: ~h*~). + Timestamp-related predicates now accept an optional ~:with-time~ argument, which allows matching timestamps with or without times (i.e. HH:MM). ++ Sorting method ~reverse~. *Changed* ++ The order in which sorting functions is applied has been reversed. For example, ~:sort '(todo priority date)~ now does what ~:sort '(date priority todo)~ did in earlier versions. (This change is made to enable the new ~reverse~ sorting method.) Users who have customized =org-ql-views= will need to update the stored views' sorting methods to preserve the desired sort order. + Helm support (including the command =helm-org-ql=) has been moved to a separate package, =helm-org-ql=. + Predicate ~heading~ now matches plain strings instead of regular expressions. + Update =dash= dependency, and remove dependency on obsolete =dash-functional=. (Fixes [[https://github.com/alphapapa/org-ql/issues/179][#179]], [[https://github.com/alphapapa/org-ql/issues/209][#209]]. Thanks to [[https://github.com/landakram][Mark Hudnall]], [[https://github.com/akirak][Akira Komamura]], [[https://github.com/natask][Nathanael kinfe]], [[https://github.com/benthamite][Pablo Stafforini]], [[https://github.com/jmay][Jason May]], and [[https://github.com/basil-conto][Basil L. Contovounesios]].) diff --git a/examples.org b/examples.org index 7d5f28de..1c5ef9d2 100644 --- a/examples.org +++ b/examples.org @@ -35,7 +35,7 @@ Show an agenda-like view, similar to a "traditional" Org Agenda with Log Mode tu (scheduled :to today) (ts-active :on today))) (closed :on today)) - :sort '(date priority todo)) + :sort '(todo priority date)) #+END_SRC Another example, showing grouping with [[https://github.com/alphapapa/org-super-agenda][org-super-agenda]]: @@ -76,7 +76,7 @@ Show entries that have any timestamp within the past week. Group by date using (org-ql-search (org-agenda-files) '(ts :from -7 :to today) :title "Recent Items" - :sort '(date priority todo) + :sort '(todo priority date) :super-groups '((:auto-ts t))) #+END_SRC diff --git a/org-ql-view.el b/org-ql-view.el index 773c47f5..fbfd57b5 100644 --- a/org-ql-view.el +++ b/org-ql-view.el @@ -132,13 +132,13 @@ See info node `(elisp)Cyclic Window Ordering'." (deadline auto) (scheduled :to today) (ts-active :on today))) - :sort '(date priority todo) + :sort '(todo priority date) :super-groups 'org-super-agenda-groups :title "Agenda-like")) (cons "Overview: NEXT tasks" (list :buffers-files #'org-agenda-files :query '(todo "NEXT") - :sort '(priority date) + :sort '(date priority) :super-groups 'org-super-agenda-groups :title "Overview: NEXT tasks")) (cons "Calendar: Today" @@ -189,7 +189,7 @@ See info node `(elisp)Cyclic Window Ordering'." (ancestors (done))) :title (propertize "Review: Dangling tasks" 'help-echo "Tasks whose ancestor is done") - :sort '(date priority todo) + :sort '(todo priority date) :super-groups '((:auto-parent t)))) (cons (propertize "Review: Stale tasks" 'help-echo "Tasks without a timestamp in the past 2 weeks") @@ -198,7 +198,7 @@ See info node `(elisp)Cyclic Window Ordering'." (not (ts :from -14))) :title (propertize "Review: Stale tasks" 'help-echo "Tasks without a timestamp in the past 2 weeks") - :sort '(date priority todo) + :sort '(todo priority date) :super-groups '((:auto-parent t)))) (cons (propertize "Review: Stuck projects" 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") @@ -208,7 +208,7 @@ See info node `(elisp)Cyclic Window Ordering'." (not (descendants (todo "NEXT")))) :title (propertize "Review: Stuck projects" 'help-echo "Tasks with sub-tasks but no NEXT sub-tasks") - :sort '(priority date) + :sort '(date priority) :super-groups 'org-super-agenda-groups))) "Alist of `org-ql-view' commands." :type @@ -230,6 +230,7 @@ See info node `(elisp)Cyclic Window Ordering'." (const todo) (const priority) (const random) + (const reverse) (function :tag "Custom comparator")))) ((const :tag "Group-by" :super-groups) (choice (variable-item :tag "Default org-super-agenda groups" org-super-agenda-groups) @@ -282,7 +283,7 @@ TYPE may be `ts', `ts-active', `ts-inactive', `clocked', or `(,type :from ,(- num-days) :to 0))))) (org-ql-search files query :title "Recent items" - :sort '(date priority todo) + :sort '(todo priority date) :super-groups groups))) ;;;###autoload @@ -1110,6 +1111,7 @@ The counterpart to `org-ql-view--contract-buffers-files'." "deadline" "priority" "random" + "reverse" "scheduled" "todo") nil nil (when org-ql-view-sort diff --git a/org-ql.el b/org-ql.el index 193592a0..ac2e5418 100644 --- a/org-ql.el +++ b/org-ql.el @@ -349,9 +349,17 @@ widen and search the entire buffer). SORT is either nil, in which case items are not sorted; or one or a list of defined `org-ql' sorting methods (`date', `deadline', -`scheduled', `todo', `priority', or `random'); or a user-defined -comparator function that accepts two items as arguments and -returns nil or non-nil." +`scheduled', `todo', `priority', `reverse', or `random'); or a +user-defined comparator function that accepts two items as +arguments and returns nil or non-nil. Sorting methods are +applied in the order given (i.e. later methods override earlier +ones), and `reverse' may be used more than once. + +For example, `(date priority)' would present items with the +highest priority first, and within each priority the oldest items +would appear first. In contrast, `(date reverse priority)' would +also present items with the highest priority first, but within +each priority the newest items would appear first." (declare (indent defun)) (-let* ((buffers (->> (cl-typecase buffers-or-files (null (list (current-buffer))) @@ -418,8 +426,7 @@ returns nil or non-nil." ;; Sort items (pcase sort (`nil items) - ((guard (cl-loop for elem in (-list sort) - always (memq elem '(date deadline scheduled todo priority random)))) + ((guard (cl-subsetp (-list sort) '(date deadline scheduled todo priority random reverse))) ;; Default sorting functions (org-ql--sort-by items (-list sort))) ;; Sort by user-given comparator. @@ -2170,7 +2177,7 @@ PREDICATES is a list of one or more sorting methods, including: ('priority #'org-ql--priority<) ('random (lambda (&rest _ignore) (= 0 (random 2)))) - ;; NOTE: 'todo is handled below + ;; NOTE: reverse and todo are handled below. ;; TODO: Add more. (_ (user-error "Invalid sorting predicate: %s" symbol)))) (sort-by-todo-keyword (items) @@ -2183,11 +2190,16 @@ PREDICATES is a list of one or more sorting methods, including: ;; Put at end of list if not found (1+ (length org-todo-keywords-1))))))) (-flatten-n 1 (-map #'cdr sorted-groups))))) - (cl-loop for pred in (reverse predicates) - do (setq items (if (eq pred 'todo) - (sort-by-todo-keyword items) - (-sort (sorter pred) items))) - finally return items))) + (dolist (pred predicates) + (setq items (pcase pred + ;; NOTE: Using `reverse' instead of `nreverse' because my gut + ;; tells me that, while `nreverse' would be preferable and faster, + ;; it would probably cause weird bugs, like items' order being + ;; reversed every time a cached query is refreshed in a view. + ('reverse (reverse items)) + ('todo (sort-by-todo-keyword items)) + (_ (-sort (sorter pred) items))))) + items)) ;; TODO: Rewrite date sorters using `ts'. diff --git a/org-ql.info b/org-ql.info index 41e5b1f6..851f6f00 100644 --- a/org-ql.info +++ b/org-ql.info @@ -995,8 +995,15 @@ File: README.info, Node: 06-pre, Next: 052, Up: Changelog • Timestamp-related predicates now accept an optional ‘:with-time’ argument, which allows matching timestamps with or without times (i.e. HH:MM). + • Sorting method ‘reverse’. *Changed* + • The order in which sorting functions is applied has been reversed. + For example, ‘:sort '(todo priority date)’ now does what ‘:sort + '(date priority todo)’ did in earlier versions. (This change is + made to enable the new ‘reverse’ sorting method.) Users who have + customized org-ql-views will need to update the stored views’ + sorting methods to preserve the desired sort order. • Helm support (including the command helm-org-ql) has been moved to a separate package, helm-org-ql. • Predicate ‘heading’ now matches plain strings instead of regular @@ -1568,31 +1575,31 @@ Node: Links35328 Node: Tips36015 Node: Changelog36333 Node: 06-pre37059 -Node: 05239177 -Node: 05139481 -Node: 0539898 -Node: 04941372 -Node: 04841646 -Node: 04741993 -Node: 04642388 -Node: 04542788 -Node: 04443147 -Node: 04343506 -Node: 04243703 -Node: 04143864 -Node: 0444105 -Node: 03248038 -Node: 03148417 -Node: 0348614 -Node: 02351589 -Node: 02251817 -Node: 02152085 -Node: 0252284 -Node: 0156319 -Node: Notes56420 -Node: Comparison with Org Agenda searches56582 -Node: org-sidebar57454 -Node: License57733 +Node: 05239636 +Node: 05139940 +Node: 0540357 +Node: 04941831 +Node: 04842105 +Node: 04742452 +Node: 04642847 +Node: 04543247 +Node: 04443606 +Node: 04343965 +Node: 04244162 +Node: 04144323 +Node: 0444564 +Node: 03248497 +Node: 03148876 +Node: 0349073 +Node: 02352048 +Node: 02252276 +Node: 02152544 +Node: 0252743 +Node: 0156778 +Node: Notes56879 +Node: Comparison with Org Agenda searches57041 +Node: org-sidebar57913 +Node: License58192  End Tag Table