Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extra Priority Values (A-Z and 0-64) #313

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 23 additions & 15 deletions org-ql.el
Original file line number Diff line number Diff line change
Expand Up @@ -1735,29 +1735,28 @@ priority B)."
`(priority ',comparator ,letter)))

:preambles
(;; NOTE: This only accepts A, B, or C. I haven't seen
;; other priorities in the wild, so this will do for now.
(`(,predicate-names)
((`(,predicate-names)
;; Any priority cookie.
(list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) "[#" (in "ABC") "]") t)))
(list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (0+ nonl) "[#" (or (in "A-Z") (1+ (in "0-9"))) "]") t)))
(`(,predicate-names ,(and (or ''= ''< ''> ''<= ''>=) comparator) ,letter)
;; Comparator and priority letter.
;; NOTE: The double-quoted comparators. See below.
(let* ((priority-letters '("A" "B" "C"))
(let* ((priority-letters (append (mapcar #'number-to-string (number-sequence 0 64))
(mapcar #'string (number-sequence ?A ?Z))))
(index (-elem-index letter priority-letters))
;; NOTE: Higher priority == lower number.
;; NOTE: Because we need to support both preamble-based queries and
;; regular predicate ones, we work around an idiosyncrasy of query
;; pre-processing by accepting both quoted and double-quoted comparator
;; function symbols. Not the most elegant solution, but it works.
(priorities (s-join "" (pcase comparator
((or '= ''=) (list letter))
((or '> ''>) (cl-subseq priority-letters 0 index))
((or '>= ''>=) (cl-subseq priority-letters 0 (1+ index)))
((or '< ''<) (cl-subseq priority-letters (1+ index)))
((or '<= ''<=) (cl-subseq priority-letters index))))))
(priorities (pcase comparator
((or '= ''=) (list letter))
((or '> ''>) (cl-subseq priority-letters 0 index))
((or '>= ''>=) (cl-subseq priority-letters 0 (1+ index)))
((or '< ''<) (cl-subseq priority-letters (1+ index)))
((or '<= ''<=) (cl-subseq priority-letters index)))))
(list :regexp (rx-to-string `(seq bol (1+ "*") (1+ blank) (optional (1+ upper) (1+ blank))
"[#" (in ,priorities) "]") t))))
"[#" (or ,@priorities) "]") t))))
(`(,predicate-names . ,letters)
;; One or more priorities.
;; MAYBE: Disable case-folding.
Expand All @@ -1780,11 +1779,11 @@ priority B)."
(`(,(and (or '= '< '> '<= '>=) comparator) ,priority-arg)
;; Comparator and priority arguments given: compare item priority using them.
(funcall comparator item-priority
(* 1000 (- org-lowest-priority (string-to-char priority-arg)))))
(org-get-priority (format "[#%s]" priority-arg))))
(_
;; List of priorities given as arguments: compare each of them to item priority using =.
(cl-loop for priority-arg in args
thereis (= item-priority (* 1000 (- org-lowest-priority (string-to-char priority-arg)))))))))
thereis (= item-priority (org-get-priority (format "[#%s]" priority-arg))))))))

(org-ql-defpred property (property &optional value &key inherit)
"Return non-nil if current entry has PROPERTY, and optionally VALUE.
Expand Down Expand Up @@ -2501,11 +2500,20 @@ A and B are Org timestamp elements."
(a-ts t)
(b-ts nil)))))

(defun org-ql--priority-to-value (el)
"Return an integer suitable for sorting priorities."
(let ((prio (org-element-property :priority el)))
(cond
((not prio) (org-priority-to-value (org-element-property :raw-value el)))
((not (integerp prio)) nil)
((<= ?0 prio ?9) (- prio ?0))
(t prio))))

(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-macrolet ((priority (item)
`(org-element-property :priority ,item)))
`(org-ql--priority-to-value ,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)))
Expand Down
6 changes: 3 additions & 3 deletions tests/data.org
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ SCHEDULED: <2017-07-05 Wed 18:00>
:Effort: 5
:END:

* TODO [#C] Get haircut :personal:@town:
* TODO [#Z] Get haircut :personal:@town:
SCHEDULED: <2017-07-05 Wed>

Should probably do this before I take over the world. Want to look my best. (Not that it will matter once I'm in charge.)

* TODO [#B] Internet :bills:
* TODO [#1] Internet :bills:
DEADLINE: <2017-07-21 Fri -1m>

* TODO [#A] Spaceship lease :bills:spaceship:
Expand All @@ -76,7 +76,7 @@ DEADLINE: <2017-08-01 Tue -1m>
:agenda-group: bills
:END:

* TODO [#B] Fix flux capacitor :spaceship:shopping:@computer:
* TODO [#9] Fix flux capacitor :spaceship:shopping:@computer:
SCHEDULED: <2017-07-05 Wed>

If I don't, the frobnicator will probably fall off halfway to Mars...
Expand Down
12 changes: 9 additions & 3 deletions tests/test-org-ql.el
Original file line number Diff line number Diff line change
Expand Up @@ -1324,13 +1324,19 @@ with keyword arg NOW in PLIST."
'("Take over the moon" "Get haircut")))
(org-ql-it "<= a priority"
(org-ql-expect ('(priority <= "B"))
'("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut" "Internet" "Fix flux capacitor")))
'("Take over Mars" "Take over the moon" "Renew membership in supervillain club" "Learn universal sign language" "Get haircut")))
(org-ql-it "> a priority"
(org-ql-expect ('(priority > "B"))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Spaceship lease")))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Internet" "Spaceship lease" "Fix flux capacitor")))
(org-ql-it ">= a priority"
(org-ql-expect ('(priority >= "B"))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor"))))
'("Take over the universe" "Take over the world" "Skype with president of Antarctica" "Take over Mars" "Renew membership in supervillain club" "Learn universal sign language" "Internet" "Spaceship lease" "Fix flux capacitor")))
(org-ql-it "compare numerical priorities"
(org-ql-expect ('(priority > "5"))
'("Internet")))
(org-ql-it "compare double-digit numerical priorities"
(org-ql-expect ('(priority > "60"))
'("Internet" "Fix flux capacitor"))))

(describe "(property)"

Expand Down