aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pearl.el42
-rw-r--r--tests/test-pearl-adhoc.el61
-rw-r--r--tests/test-pearl-keymap.el3
3 files changed, 102 insertions, 4 deletions
diff --git a/pearl.el b/pearl.el
index 8ea24d2..5cd1373 100644
--- a/pearl.el
+++ b/pearl.el
@@ -3212,8 +3212,15 @@ Interactively, completes over the configured query names. Compiles the stored
filter, fetches, sorts per the query's `:sort'/`:order', and renders into the
active file with the query recorded as the source."
(interactive
- (list (completing-read "Saved query: "
- (mapcar #'car pearl-saved-queries) nil t)))
+ (list (if (null pearl-saved-queries)
+ (user-error "No saved queries configured")
+ (completing-read
+ "Saved query: "
+ (pearl--completion-table-keep-order
+ (pearl--with-none (mapcar #'car pearl-saved-queries)))
+ nil t))))
+ (when (pearl--filter-none-value-p name)
+ (user-error "Cancelled; no saved query run"))
(let ((entry (assoc name pearl-saved-queries)))
(unless entry
(user-error "No saved query named %s" name))
@@ -3447,6 +3454,33 @@ choice; selecting it drops that dimension. The assignee prompt offers `me'
:test #'string=))))
open state project labels assignee)))
+;;;###autoload
+(defun pearl-delete-saved-query (name)
+ "Delete the saved query NAME from `pearl-saved-queries' after confirmation.
+Interactively, completes over the configured query names with
+`pearl--filter-none' at the top as a cancel. Local-only: removes the entry
+from the customized list and persists via `customize-save-variable'. Linear
+is untouched (saved queries are local; syncing them up is a separate spec)."
+ (interactive
+ (list (if (null pearl-saved-queries)
+ (user-error "No saved queries to delete")
+ (completing-read
+ "Delete saved query: "
+ (pearl--completion-table-keep-order
+ (pearl--with-none (mapcar #'car pearl-saved-queries)))
+ nil t))))
+ (cond
+ ((pearl--filter-none-value-p name)
+ (message "Cancelled; no saved query deleted"))
+ ((not (assoc name pearl-saved-queries))
+ (user-error "No saved query named %s" name))
+ ((yes-or-no-p (format "Delete saved query %s? " name))
+ (setq pearl-saved-queries
+ (cl-remove name pearl-saved-queries :key #'car :test #'string=))
+ (customize-save-variable 'pearl-saved-queries pearl-saved-queries)
+ (message "Deleted saved query %s" name))
+ (t (message "Kept saved query %s" name))))
+
(defun pearl--save-query (name filter-plist &optional sort order)
"Save FILTER-PLIST as the saved query NAME, replacing any entry of that NAME.
Persists `pearl-saved-queries' via Customize. SORT and ORDER are
@@ -5153,7 +5187,8 @@ body stay."
("c" "create comment" pearl-create-comment)]
["Delete"
("k" "delete issue" pearl-delete-current-issue)
- ("K" "delete comment" pearl-delete-current-comment)]]
+ ("K" "delete comment" pearl-delete-current-comment)
+ ("q" "delete saved query" pearl-delete-saved-query)]]
["Workspace"
["Fetch"
("P" "pick source" pearl-pick-source)
@@ -5227,6 +5262,7 @@ body stay."
(let ((map (make-sparse-keymap)))
(define-key map "t" (cons "delete issue" #'pearl-delete-current-issue))
(define-key map "c" (cons "delete comment" #'pearl-delete-current-comment))
+ (define-key map "q" (cons "delete saved query" #'pearl-delete-saved-query))
map)
"Pearl delete commands; a sub-keymap of `pearl-prefix-map'.")
diff --git a/tests/test-pearl-adhoc.el b/tests/test-pearl-adhoc.el
index 2bcc575..2dec1a3 100644
--- a/tests/test-pearl-adhoc.el
+++ b/tests/test-pearl-adhoc.el
@@ -124,6 +124,67 @@ candidate list, so completion still works the way the framework expects."
(should (equal '(:priority 1)
(plist-get (cdr (assoc "Dup" pearl-saved-queries)) :filter))))))
+;;; pearl-delete-saved-query
+
+(ert-deftest test-pearl-delete-saved-query-removes-entry-on-yes ()
+ "Confirming the prompt removes the named entry and persists."
+ (let ((pearl-saved-queries '(("Keep" :filter (:open t))
+ ("Drop" :filter (:priority 1))))
+ (persisted nil))
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest _) t))
+ ((symbol-function 'customize-save-variable)
+ (lambda (&rest _) (setq persisted t))))
+ (pearl-delete-saved-query "Drop")
+ (should-not (assoc "Drop" pearl-saved-queries))
+ (should (assoc "Keep" pearl-saved-queries))
+ (should persisted))))
+
+(ert-deftest test-pearl-delete-saved-query-no-at-confirm-keeps-entry ()
+ "Declining the confirm prompt leaves the entry in place and does not persist."
+ (let ((pearl-saved-queries '(("Keep" :filter (:open t))))
+ (persisted nil))
+ (cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest _) nil))
+ ((symbol-function 'customize-save-variable)
+ (lambda (&rest _) (setq persisted t))))
+ (pearl-delete-saved-query "Keep")
+ (should (assoc "Keep" pearl-saved-queries))
+ (should-not persisted))))
+
+(ert-deftest test-pearl-delete-saved-query-sentinel-cancels ()
+ "Picking the `pearl--filter-none' sentinel cancels without touching anything."
+ (let ((pearl-saved-queries '(("Keep" :filter (:open t))))
+ (confirmed nil))
+ (cl-letf (((symbol-function 'yes-or-no-p)
+ (lambda (&rest _) (setq confirmed t) t))
+ ((symbol-function 'customize-save-variable)
+ (lambda (&rest _) nil)))
+ (pearl-delete-saved-query pearl--filter-none)
+ (should (assoc "Keep" pearl-saved-queries))
+ (should-not confirmed))))
+
+(ert-deftest test-pearl-delete-saved-query-unknown-name-errors ()
+ "An unknown name (e.g. typed past completion) signals a user-error."
+ (let ((pearl-saved-queries '(("Keep" :filter (:open t)))))
+ (should-error (pearl-delete-saved-query "Nope") :type 'user-error)))
+
+(ert-deftest test-pearl-delete-saved-query-empty-list-errors-on-interactive ()
+ "Called interactively with no saved queries, the command errors cleanly
+rather than offering an empty picker."
+ (let ((pearl-saved-queries nil))
+ (should-error (call-interactively #'pearl-delete-saved-query)
+ :type 'user-error)))
+
+;;; pearl-run-saved-query sentinel cancel
+
+(ert-deftest test-pearl-run-saved-query-sentinel-cancels ()
+ "Picking the `pearl--filter-none' sentinel cancels the run without fetching."
+ (let ((fetched nil)
+ (pearl-saved-queries '(("Open" :filter (:open t)))))
+ (cl-letf (((symbol-function 'pearl--query-issues-async)
+ (lambda (&rest _) (setq fetched t))))
+ (should-error (pearl-run-saved-query pearl--filter-none) :type 'user-error)
+ (should-not fetched))))
+
;;; pearl-list-issues-filtered
(ert-deftest test-pearl-list-issues-filtered-runs-with-source ()
diff --git a/tests/test-pearl-keymap.el b/tests/test-pearl-keymap.el
index 5cc658d..d04e309 100644
--- a/tests/test-pearl-keymap.el
+++ b/tests/test-pearl-keymap.el
@@ -89,7 +89,8 @@ The lowercase `c' is no longer a direct command -- it is the create prefix."
(should (eq 'pearl-create-issue (lookup-key pearl-prefix-map (kbd "c t"))))
(should (eq 'pearl-create-comment (lookup-key pearl-prefix-map (kbd "c c"))))
(should (eq 'pearl-delete-current-issue (lookup-key pearl-prefix-map (kbd "k t"))))
- (should (eq 'pearl-delete-current-comment (lookup-key pearl-prefix-map (kbd "k c")))))
+ (should (eq 'pearl-delete-current-comment (lookup-key pearl-prefix-map (kbd "k c"))))
+ (should (eq 'pearl-delete-saved-query (lookup-key pearl-prefix-map (kbd "k q")))))
(ert-deftest test-pearl-prefix-map-open-and-copy-groups ()
"The open group resolves the two open actions; copy resolves copy-url."