aboutsummaryrefslogtreecommitdiff
path: root/pearl.el
diff options
context:
space:
mode:
Diffstat (limited to 'pearl.el')
-rw-r--r--pearl.el36
1 files changed, 30 insertions, 6 deletions
diff --git a/pearl.el b/pearl.el
index 0ecc03a..9aebcef 100644
--- a/pearl.el
+++ b/pearl.el
@@ -849,13 +849,15 @@ PRIORITY is an integer 0-4 or a symbol in `pearl--priority-symbols'."
(defun pearl--compile-state-filter (plist)
"Return the state sub-filter alist for PLIST, or nil when no state key is set.
-An explicit `:state' (name) or `:state-type' (one type or a list) takes
-precedence over `:open', the broad not-closed predicate."
+An explicit `:state' (a name or a list of names) or `:state-type' (one type or
+a list) takes precedence over `:open', the broad not-closed predicate."
(let ((state (plist-get plist :state))
(state-type (plist-get plist :state-type))
(open (plist-get plist :open)))
(cond
- (state (list (cons "name" (pearl--eq state))))
+ (state (list (cons "name" (if (listp state)
+ (pearl--in state)
+ (pearl--eq state)))))
(state-type (list (cons "type"
(pearl--in (if (listp state-type)
state-type
@@ -984,8 +986,18 @@ multi-value filter would change which issues match."
((or (assq 'and node) (assq 'or node))
(pearl--rc-refuse "state uses OR logic Pearl can't represent"))
((assq 'name node)
- (let ((r (pearl--rc-scalar (cdr (assq 'name node)) "state.name")))
- (if (eq (car r) 'ok) (cons 'ok (list :state (cdr r))) r)))
+ ;; :state is plural-capable (a name or a list), like :state-type:
+ ;; name.eq / name.in[one] -> scalar, name.in[many] -> list.
+ (let ((op (cdr (assq 'name node))))
+ (cond
+ ((assq 'eq op) (cons 'ok (list :state (cdr (assq 'eq op)))))
+ ((assq 'in op)
+ (let ((vals (append (cdr (assq 'in op)) nil)))
+ (cond
+ ((null vals) (pearl--rc-refuse "state.name has an empty `in'"))
+ ((= 1 (length vals)) (cons 'ok (list :state (car vals))))
+ (t (cons 'ok (list :state vals))))))
+ (t (pearl--rc-refuse "state.name uses an operator Pearl can't represent")))))
((assq 'type node)
(let ((op (cdr (assq 'type node))))
(cond
@@ -1126,7 +1138,7 @@ needs team context) is resolved upstream, not here."
(let ((order (plist-get plist :order)))
(when (and order (not (memq order '(asc desc))))
(user-error ":order must be `asc' or `desc', got %S" order)))
- (dolist (key '(:state :project :team :cycle :assignee-id :label-id))
+ (dolist (key '(:project :team :cycle :assignee-id :label-id))
(let ((val (plist-get plist key)))
(when (and (stringp val) (string-empty-p val))
(user-error "%s must not be an empty string" key))))
@@ -1136,6 +1148,18 @@ needs team context) is resolved upstream, not here."
(cl-some (lambda (x) (not (and (stringp x) (not (string-empty-p x)))))
labels)))
(user-error ":labels must be a list of non-empty strings")))
+ ;; :state is a single name OR a list of non-empty names (mirrors :labels).
+ (let ((state (plist-get plist :state)))
+ (cond
+ ((null state))
+ ((stringp state)
+ (when (string-empty-p state)
+ (user-error ":state must not be an empty string")))
+ ((listp state)
+ (when (cl-some (lambda (x) (not (and (stringp x) (not (string-empty-p x)))))
+ state)
+ (user-error ":state must be a name or a list of non-empty names")))
+ (t (user-error ":state must be a name or a list of names, got %S" state))))
t)
;;; Issue Model Normalization