From 9193edf360207dc05787ed077f7bd882619b2050 Mon Sep 17 00:00:00 2001 From: John Buckley Date: Fri, 29 May 2026 16:45:32 +0100 Subject: [PATCH 1/3] Add agent-shell-session-prompt-choices defcustom --- README.org | 2 + agent-shell.el | 205 +++++++++++++++++++++++++++++-------- tests/agent-shell-tests.el | 47 +++++++++ 3 files changed, 210 insertions(+), 44 deletions(-) diff --git a/README.org b/README.org index b3a4f451..3b0c9c45 100644 --- a/README.org +++ b/README.org @@ -822,9 +822,11 @@ always go to Evil modes if you need to with ~C-z~). | agent-shell-qwen-acp-command | Command and parameters for the Qwen Code client. | | agent-shell-qwen-authentication | Configuration for Qwen Code authentication. | | agent-shell-qwen-environment | Environment variables for the Qwen Code client. | +| agent-shell-session-prompt-choices | Choices to show in the session selection prompt. | | agent-shell-session-restore-verbosity | How much prior context to show when restoring a session. | | agent-shell-screenshot-command | The program to use for capturing screenshots. | | agent-shell-section-functions | Abnormal hook run after overlays are applied (experimental). | +| agent-shell-session-prompt-choices | Choices to show in the session selection prompt. | | agent-shell-session-strategy | How to handle sessions when starting a new shell. | | agent-shell-show-busy-indicator | Non-nil to show the busy indicator animation in the header and mode line. | | agent-shell-show-config-icons | Whether to show icons in agent config selection. | diff --git a/agent-shell.el b/agent-shell.el index 6502399d..603bf1f0 100644 --- a/agent-shell.el +++ b/agent-shell.el @@ -692,6 +692,41 @@ Available values: (set-default sym value)) :group 'agent-shell) +(defcustom agent-shell-session-prompt-choices nil + "Choices to show in the session selection prompt. + +The session selection prompt offers a set of options when starting +a new shell: \"Start new shell\", \"New Downloads shell\", \"New +temp shell\", \"Switch to shell buffer\" (when other shells exist), +and one entry per existing ACP session. + +When nil (the default), all choices are shown. Otherwise, the +value is a list of keyword kinds; only choices whose kind appears +in the list are shown. Valid kinds are: + + `:new-shell' Start a new shell. + `:downloads-shell' Start a new downloads shell. + `:temp-shell' Start a new temporary shell. + `:other-shell' Switch to an existing shell buffer. + `:acp-session' Resume a previously saved ACP session. + +To always start a new shell without prompting, use +`agent-shell-session-strategy' with value `new' or `new-deferred' +instead. + +Example (only show \"Start new shell\" and previous sessions): + + (setq agent-shell-session-prompt-choices + \\='(:new-shell :acp-session))" + :type '(choice (const :tag "Show all choices" nil) + (set :tag "Show selected kinds" + (const :tag "Start new shell" :new-shell) + (const :tag "New Downloads shell" :downloads-shell) + (const :tag "New temp shell" :temp-shell) + (const :tag "Switch to existing shell buffer" :other-shell) + (const :tag "Resume previous ACP session" :acp-session))) + :group 'agent-shell) + (defvar agent-shell-idle-timeout 30 "Seconds before an `idle' event is emitted. @@ -4976,6 +5011,35 @@ MAX-WIDTHS is an alist mapping column symbols to their max widths." (push (if face (propertize padded 'face face) padded) parts))) (apply #'concat (nreverse parts)))) +(defun agent-shell--filter-session-prompt-choices (choices) + "Filter CHOICES by `agent-shell-session-prompt-choices'. + +CHOICES is a list of alists, each shaped: + ((:kind . KIND) (:label . LABEL) (:value . VALUE)) + +When `agent-shell-session-prompt-choices' is nil, returns CHOICES +unchanged. Otherwise, retains only those choices whose :kind is +listed in `agent-shell-session-prompt-choices'. + +Example: + (let ((agent-shell-session-prompt-choices \\='(:new-shell :acp-session))) + (agent-shell--filter-session-prompt-choices + \\='(((:kind . :new-shell) + (:label . \"Start new shell\") + (:value . nil)) + ((:kind . :temp-shell) + (:label . \"New temp shell\") + (:value . :temp-shell))))) + => (((:kind . :new-shell) + (:label . \"Start new shell\") + (:value . nil)))" + (if (null agent-shell-session-prompt-choices) + choices + (seq-filter (lambda (choice) + (memq (map-elt choice :kind) + agent-shell-session-prompt-choices)) + choices))) + (defun agent-shell--prompt-select-session (acp-sessions) "Prompt to choose one from ACP-SESSIONS. @@ -4997,19 +5061,29 @@ Falls back to latest session in batch mode (e.g. tests)." (length (agent-shell--session-column-value col s))) acp-sessions)))) columns))) - ;; TODO: Consolidate choices with `agent-shell--shell-buffer'. - (session-choices (append (list (cons new-session-choice nil) - (cons "New Downloads shell" :downloads-shell) - (cons "New temp shell" :temp-shell)) - (when other-shells - (list (cons "Switch to shell buffer" :other-shell))) - (mapcar (lambda (acp-session) - (cons (agent-shell--session-choice-label - :acp-session acp-session - :max-widths max-widths) - acp-session)) - acp-sessions))) - (candidates (mapcar #'car session-choices)) + (session-choices + (agent-shell--filter-session-prompt-choices + (append (list `((:kind . :new-shell) + (:label . ,new-session-choice) + (:value . nil)) + '((:kind . :downloads-shell) + (:label . "New Downloads shell") + (:value . :downloads-shell)) + '((:kind . :temp-shell) + (:label . "New temp shell") + (:value . :temp-shell))) + (when other-shells + (list '((:kind . :other-shell) + (:label . "Switch to shell buffer") + (:value . :other-shell)))) + (mapcar (lambda (acp-session) + `((:kind . :acp-session) + (:label . ,(agent-shell--session-choice-label + :acp-session acp-session + :max-widths max-widths)) + (:value . ,acp-session))) + acp-sessions)))) + (candidates (mapcar (lambda (c) (map-elt c :label)) session-choices)) ;; Some completion frameworks yielded appended (nil) to each line ;; unless this-command was bound. ;; @@ -5019,37 +5093,40 @@ Falls back to latest session in batch mode (e.g. tests)." ;; Let's optimize the rocket engine Feb 12, 21:02 (nil) (this-command 'agent-shell)) (agent-shell--emit-event :event 'session-prompt) - (let ((selection (completing-read "Start shell (default: new): " - (lambda (string pred action) - (if (eq action 'metadata) - '(metadata - (display-sort-function . identity) - (eager-display . t) - (eager-update . t)) - (complete-with-action action candidates string pred))) - nil t nil nil - new-session-choice))) - (pcase (map-elt session-choices selection) - (:other-shell - (let ((other-shell (agent-shell--read-shell-buffer - :prompt "Switch to shell buffer: " - :buffers other-shells)) - (bootstrapping-shell (map-elt (agent-shell--state) :buffer))) - (agent-shell--display-buffer other-shell) - (kill-buffer bootstrapping-shell) - :other-shell)) - (:downloads-shell - (let ((config (map-elt (agent-shell--state) :agent-config))) - (kill-buffer (map-elt (agent-shell--state) :buffer)) - (agent-shell-new-downloads-shell :config config)) - :other-shell) - (:temp-shell - (let ((config (map-elt (agent-shell--state) :agent-config))) - (kill-buffer (map-elt (agent-shell--state) :buffer)) - (agent-shell-new-temp-shell :config config)) - :other-shell) - (choice choice))))))) - + (when candidates + (let* ((selection (completing-read "Start shell (default: new): " + (lambda (string pred action) + (if (eq action 'metadata) + '(metadata + (display-sort-function . identity) + (eager-display . t) + (eager-update . t)) + (complete-with-action action candidates string pred))) + nil t nil nil + new-session-choice)) + (value (map-elt (seq-find (lambda (c) (equal (map-elt c :label) selection)) + session-choices) + :value))) + (pcase value + (:other-shell + (let ((other-shell (agent-shell--read-shell-buffer + :prompt "Switch to shell buffer: " + :buffers other-shells)) + (bootstrapping-shell (map-elt (agent-shell--state) :buffer))) + (agent-shell--display-buffer other-shell) + (kill-buffer bootstrapping-shell) + :other-shell)) + (:downloads-shell + (let ((config (map-elt (agent-shell--state) :agent-config))) + (kill-buffer (map-elt (agent-shell--state) :buffer)) + (agent-shell-new-downloads-shell :config config)) + :other-shell) + (:temp-shell + (let ((config (map-elt (agent-shell--state) :agent-config))) + (kill-buffer (map-elt (agent-shell--state) :buffer)) + (agent-shell-new-temp-shell :config config)) + :other-shell) + (choice choice)))))))) (cl-defun agent-shell--session-from-response (&key acp-response acp-session-id) "Return internal session state from ACP-RESPONSE and ACP-SESSION-ID." @@ -6041,6 +6118,7 @@ Returns a buffer object or nil." (user-error "No agent shell buffers available for current project")) (if (and (eq agent-shell-session-strategy 'new-deferred) (agent-shell-buffers)) +<<<<<<< HEAD ;; TODO: Consolidate choices with `agent-shell--prompt-select-session'. (let* ((start-new "New shell") (start-downloads "New Downloads shell") @@ -6062,6 +6140,45 @@ Returns a buffer object or nil." (error "No agent config found")) :no-focus t :new-session t)))) +======= + (let* ((choices (agent-shell--filter-session-prompt-choices + '(((:kind . :new-shell) + (:label . "New shell") + (:value . :new-shell)) + ((:kind . :downloads-shell) + (:label . "New Downloads shell") + (:value . :downloads-shell)) + ((:kind . :temp-shell) + (:label . "New temp shell") + (:value . :temp-shell)) + ((:kind . :other-shell) + (:label . "Switch to shell buffer") + (:value . :other-shell))))) + (selection (when choices + (completing-read "Start shell (default: new): " + (mapcar (lambda (c) (map-elt c :label)) choices) + nil t))) + (value (when selection + (map-elt (seq-find (lambda (c) (equal (map-elt c :label) selection)) + choices) + :value)))) + (pcase value + (:other-shell + (get-buffer (completing-read "Switch to shell buffer: " + (mapcar #'buffer-name (agent-shell-buffers)) + nil t))) + (:downloads-shell + (agent-shell-new-downloads-shell :no-display t)) + (:temp-shell + (agent-shell-new-temp-shell :no-display t)) + (_ + (agent-shell--start :config (or (agent-shell--resolve-preferred-config) + (agent-shell-select-config + :prompt "Start new agent: ") + (error "No agent config found")) + :no-focus t + :new-session t)))) +>>>>>>> 47b8a29 (Add agent-shell-session-prompt-choices defcustom) (agent-shell--start :config (or (agent-shell--resolve-preferred-config) (agent-shell-select-config :prompt "Start new agent: ") diff --git a/tests/agent-shell-tests.el b/tests/agent-shell-tests.el index 441f0eda..d3b54cae 100644 --- a/tests/agent-shell-tests.el +++ b/tests/agent-shell-tests.el @@ -1890,6 +1890,53 @@ and rejects `new-deferred' and other unknown values." (should-error (agent-shell--validate-session-strategy 'bogus) :type 'user-error)) +(ert-deftest agent-shell--filter-session-prompt-choices-nil () + "Test that nil filter passes all choices through unchanged." + (let ((agent-shell-session-prompt-choices nil) + (choices '(((:kind . :new-shell) + (:label . "Start new shell") + (:value . nil)) + ((:kind . :downloads-shell) + (:label . "New Downloads shell") + (:value . :downloads-shell)) + ((:kind . :temp-shell) + (:label . "New temp shell") + (:value . :temp-shell)) + ((:kind . :other-shell) + (:label . "Switch to shell buffer") + (:value . :other-shell)) + ((:kind . :acp-session) + (:label . "Session A") + (:value . session-a))))) + (should (equal (agent-shell--filter-session-prompt-choices choices) + choices)))) + +(ert-deftest agent-shell--filter-session-prompt-choices-list () + "Test that a list of kinds keeps only choices with matching kind." + (let ((agent-shell-session-prompt-choices '(:new-shell :acp-session))) + (should (equal (agent-shell--filter-session-prompt-choices + '(((:kind . :new-shell) + (:label . "Start new shell") + (:value . nil)) + ((:kind . :downloads-shell) + (:label . "New Downloads shell") + (:value . :downloads-shell)) + ((:kind . :temp-shell) + (:label . "New temp shell") + (:value . :temp-shell)) + ((:kind . :other-shell) + (:label . "Switch to shell buffer") + (:value . :other-shell)) + ((:kind . :acp-session) + (:label . "Session A") + (:value . session-a)))) + '(((:kind . :new-shell) + (:label . "Start new shell") + (:value . nil)) + ((:kind . :acp-session) + (:label . "Session A") + (:value . session-a))))))) + (ert-deftest agent-shell--initiate-session-strategy-new-skips-list-load () "Test `agent-shell--initiate-session' skips list/load when strategy is `new'." (with-temp-buffer From 900d1112e47f439e4c4af8c095e78a1dccd89d85 Mon Sep 17 00:00:00 2001 From: John Buckley Date: Mon, 1 Jun 2026 09:34:11 +0100 Subject: [PATCH 2/3] Add agent-shell--build-session-prompt-choices to consolidate session choice menu --- agent-shell.el | 87 ++++++++++++++++++++++---------------- tests/agent-shell-tests.el | 41 ++++++++++++++++++ 2 files changed, 91 insertions(+), 37 deletions(-) diff --git a/agent-shell.el b/agent-shell.el index 603bf1f0..bd40799e 100644 --- a/agent-shell.el +++ b/agent-shell.el @@ -696,7 +696,7 @@ Available values: "Choices to show in the session selection prompt. The session selection prompt offers a set of options when starting -a new shell: \"Start new shell\", \"New Downloads shell\", \"New +a new shell: \"New shell\", \"New Downloads shell\", \"New temp shell\", \"Switch to shell buffer\" (when other shells exist), and one entry per existing ACP session. @@ -714,13 +714,13 @@ To always start a new shell without prompting, use `agent-shell-session-strategy' with value `new' or `new-deferred' instead. -Example (only show \"Start new shell\" and previous sessions): +Example (only show \"New shell\" and previous sessions): (setq agent-shell-session-prompt-choices \\='(:new-shell :acp-session))" :type '(choice (const :tag "Show all choices" nil) (set :tag "Show selected kinds" - (const :tag "Start new shell" :new-shell) + (const :tag "New shell" :new-shell) (const :tag "New Downloads shell" :downloads-shell) (const :tag "New temp shell" :temp-shell) (const :tag "Switch to existing shell buffer" :other-shell) @@ -5025,13 +5025,13 @@ Example: (let ((agent-shell-session-prompt-choices \\='(:new-shell :acp-session))) (agent-shell--filter-session-prompt-choices \\='(((:kind . :new-shell) - (:label . \"Start new shell\") + (:label . \"New shell\") (:value . nil)) ((:kind . :temp-shell) (:label . \"New temp shell\") (:value . :temp-shell))))) => (((:kind . :new-shell) - (:label . \"Start new shell\") + (:label . \"New shell\") (:value . nil)))" (if (null agent-shell-session-prompt-choices) choices @@ -5040,6 +5040,43 @@ Example: agent-shell-session-prompt-choices)) choices))) +(cl-defun agent-shell--build-session-prompt-choices + (&key new-shell-label other-shell-p acp-sessions max-widths) + "Build the choices list shown by the session selection prompt. + +Always includes (in order) a `:new-shell' entry labeled +NEW-SHELL-LABEL, followed by `:downloads-shell' and `:temp-shell' +entries. + +When OTHER-SHELL-P is non-nil, an `:other-shell' entry is added. + +When ACP-SESSIONS is non-nil, one `:acp-session' entry is added +per session, with labels aligned using MAX-WIDTHS (see +`agent-shell--session-choice-label'). + +Each entry is an alist of the form + ((:kind . KIND) (:label . LABEL) (:value . VALUE))." + (append (list `((:kind . :new-shell) + (:label . ,new-shell-label) + (:value . nil))) + '(((:kind . :downloads-shell) + (:label . "New Downloads shell") + (:value . :downloads-shell)) + ((:kind . :temp-shell) + (:label . "New temp shell") + (:value . :temp-shell))) + (when other-shell-p + '(((:kind . :other-shell) + (:label . "Switch to shell buffer") + (:value . :other-shell)))) + (mapcar (lambda (acp-session) + `((:kind . :acp-session) + (:label . ,(agent-shell--session-choice-label + :acp-session acp-session + :max-widths max-widths)) + (:value . ,acp-session))) + acp-sessions))) + (defun agent-shell--prompt-select-session (acp-sessions) "Prompt to choose one from ACP-SESSIONS. @@ -5063,26 +5100,11 @@ Falls back to latest session in batch mode (e.g. tests)." columns))) (session-choices (agent-shell--filter-session-prompt-choices - (append (list `((:kind . :new-shell) - (:label . ,new-session-choice) - (:value . nil)) - '((:kind . :downloads-shell) - (:label . "New Downloads shell") - (:value . :downloads-shell)) - '((:kind . :temp-shell) - (:label . "New temp shell") - (:value . :temp-shell))) - (when other-shells - (list '((:kind . :other-shell) - (:label . "Switch to shell buffer") - (:value . :other-shell)))) - (mapcar (lambda (acp-session) - `((:kind . :acp-session) - (:label . ,(agent-shell--session-choice-label - :acp-session acp-session - :max-widths max-widths)) - (:value . ,acp-session))) - acp-sessions)))) + (agent-shell--build-session-prompt-choices + :new-shell-label new-session-choice + :other-shell-p other-shells + :acp-sessions acp-sessions + :max-widths max-widths))) (candidates (mapcar (lambda (c) (map-elt c :label)) session-choices)) ;; Some completion frameworks yielded appended (nil) to each line ;; unless this-command was bound. @@ -6142,18 +6164,9 @@ Returns a buffer object or nil." :new-session t)))) ======= (let* ((choices (agent-shell--filter-session-prompt-choices - '(((:kind . :new-shell) - (:label . "New shell") - (:value . :new-shell)) - ((:kind . :downloads-shell) - (:label . "New Downloads shell") - (:value . :downloads-shell)) - ((:kind . :temp-shell) - (:label . "New temp shell") - (:value . :temp-shell)) - ((:kind . :other-shell) - (:label . "Switch to shell buffer") - (:value . :other-shell))))) + (agent-shell--build-session-prompt-choices + :new-shell-label "New shell" + :other-shell-p t))) (selection (when choices (completing-read "Start shell (default: new): " (mapcar (lambda (c) (map-elt c :label)) choices) diff --git a/tests/agent-shell-tests.el b/tests/agent-shell-tests.el index d3b54cae..84c15481 100644 --- a/tests/agent-shell-tests.el +++ b/tests/agent-shell-tests.el @@ -1937,6 +1937,47 @@ and rejects `new-deferred' and other unknown values." (:label . "Session A") (:value . session-a))))))) +(ert-deftest agent-shell--build-session-prompt-choices-minimal () + "Test the builder includes new/downloads/temp by default." + (should (equal (mapcar (lambda (c) (map-elt c :kind)) + (agent-shell--build-session-prompt-choices + :new-shell-label "Start new shell")) + '(:new-shell :downloads-shell :temp-shell))) + (should (equal (map-elt (car (agent-shell--build-session-prompt-choices + :new-shell-label "Start new shell")) + :label) + "Start new shell"))) + +(ert-deftest agent-shell--build-session-prompt-choices-other-shell () + "Test the builder appends :other-shell when OTHER-SHELL-P is non-nil." + (should-not (seq-find (lambda (c) (eq (map-elt c :kind) :other-shell)) + (agent-shell--build-session-prompt-choices + :new-shell-label "Start new shell"))) + (should (seq-find (lambda (c) (eq (map-elt c :kind) :other-shell)) + (agent-shell--build-session-prompt-choices + :new-shell-label "Start new shell" + :other-shell-p t)))) + +(ert-deftest agent-shell--build-session-prompt-choices-acp-sessions () + "Test the builder appends one :acp-session per session, preserving value." + (let* ((session-a '((sessionId . "s-1") + (title . "First") + (cwd . "/tmp") + (updatedAt . "2026-01-19T14:00:00Z"))) + (session-b '((sessionId . "s-2") + (title . "Second") + (cwd . "/tmp") + (updatedAt . "2026-01-20T16:00:00Z"))) + (choices (agent-shell--build-session-prompt-choices + :new-shell-label "Start new shell" + :acp-sessions (list session-a session-b))) + (session-choices (seq-filter (lambda (c) + (eq (map-elt c :kind) :acp-session)) + choices))) + (should (equal (length session-choices) 2)) + (should (equal (map-elt (nth 0 session-choices) :value) session-a)) + (should (equal (map-elt (nth 1 session-choices) :value) session-b)))) + (ert-deftest agent-shell--initiate-session-strategy-new-skips-list-load () "Test `agent-shell--initiate-session' skips list/load when strategy is `new'." (with-temp-buffer From b9dedb15ad2865472c77a8432d98b337e67c2a86 Mon Sep 17 00:00:00 2001 From: John Buckley Date: Mon, 1 Jun 2026 20:28:36 +0100 Subject: [PATCH 3/3] Use exclusion list for session-prompt-choices --- README.org | 2 +- agent-shell.el | 34 +++++++++++++++++----------------- tests/agent-shell-tests.el | 17 +++++++++-------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/README.org b/README.org index 3b0c9c45..7ed7aa45 100644 --- a/README.org +++ b/README.org @@ -826,7 +826,7 @@ always go to Evil modes if you need to with ~C-z~). | agent-shell-session-restore-verbosity | How much prior context to show when restoring a session. | | agent-shell-screenshot-command | The program to use for capturing screenshots. | | agent-shell-section-functions | Abnormal hook run after overlays are applied (experimental). | -| agent-shell-session-prompt-choices | Choices to show in the session selection prompt. | +| agent-shell-session-prompt-exclude-choices | Kinds of choices to exclude from the session selection prompt. | | agent-shell-session-strategy | How to handle sessions when starting a new shell. | | agent-shell-show-busy-indicator | Non-nil to show the busy indicator animation in the header and mode line. | | agent-shell-show-config-icons | Whether to show icons in agent config selection. | diff --git a/agent-shell.el b/agent-shell.el index bd40799e..8a46e12b 100644 --- a/agent-shell.el +++ b/agent-shell.el @@ -692,8 +692,8 @@ Available values: (set-default sym value)) :group 'agent-shell) -(defcustom agent-shell-session-prompt-choices nil - "Choices to show in the session selection prompt. +(defcustom agent-shell-session-prompt-exclude-choices nil + "Kinds of choices to exclude from the session selection prompt. The session selection prompt offers a set of options when starting a new shell: \"New shell\", \"New Downloads shell\", \"New @@ -701,8 +701,8 @@ temp shell\", \"Switch to shell buffer\" (when other shells exist), and one entry per existing ACP session. When nil (the default), all choices are shown. Otherwise, the -value is a list of keyword kinds; only choices whose kind appears -in the list are shown. Valid kinds are: +value is a list of keyword kinds; choices whose kind appears in +the list are excluded. Valid kinds are: `:new-shell' Start a new shell. `:downloads-shell' Start a new downloads shell. @@ -714,12 +714,12 @@ To always start a new shell without prompting, use `agent-shell-session-strategy' with value `new' or `new-deferred' instead. -Example (only show \"New shell\" and previous sessions): +Example (hide the downloads and temp shell entries): - (setq agent-shell-session-prompt-choices - \\='(:new-shell :acp-session))" - :type '(choice (const :tag "Show all choices" nil) - (set :tag "Show selected kinds" + (setq agent-shell-session-prompt-exclude-choices + \\='(:downloads-shell :temp-shell))" + :type '(choice (const :tag "Exclude nothing (show all)" nil) + (set :tag "Exclude selected kinds" (const :tag "New shell" :new-shell) (const :tag "New Downloads shell" :downloads-shell) (const :tag "New temp shell" :temp-shell) @@ -5012,17 +5012,17 @@ MAX-WIDTHS is an alist mapping column symbols to their max widths." (apply #'concat (nreverse parts)))) (defun agent-shell--filter-session-prompt-choices (choices) - "Filter CHOICES by `agent-shell-session-prompt-choices'. + "Filter CHOICES by `agent-shell-session-prompt-exclude-choices'. CHOICES is a list of alists, each shaped: ((:kind . KIND) (:label . LABEL) (:value . VALUE)) -When `agent-shell-session-prompt-choices' is nil, returns CHOICES -unchanged. Otherwise, retains only those choices whose :kind is -listed in `agent-shell-session-prompt-choices'. +When `agent-shell-session-prompt-exclude-choices' is nil, returns +CHOICES unchanged. Otherwise, drops any choice whose :kind is +listed in `agent-shell-session-prompt-exclude-choices'. Example: - (let ((agent-shell-session-prompt-choices \\='(:new-shell :acp-session))) + (let ((agent-shell-session-prompt-exclude-choices \\='(:temp-shell))) (agent-shell--filter-session-prompt-choices \\='(((:kind . :new-shell) (:label . \"New shell\") @@ -5033,11 +5033,11 @@ Example: => (((:kind . :new-shell) (:label . \"New shell\") (:value . nil)))" - (if (null agent-shell-session-prompt-choices) + (if (null agent-shell-session-prompt-exclude-choices) choices - (seq-filter (lambda (choice) + (seq-remove (lambda (choice) (memq (map-elt choice :kind) - agent-shell-session-prompt-choices)) + agent-shell-session-prompt-exclude-choices)) choices))) (cl-defun agent-shell--build-session-prompt-choices diff --git a/tests/agent-shell-tests.el b/tests/agent-shell-tests.el index 84c15481..ae8e8df3 100644 --- a/tests/agent-shell-tests.el +++ b/tests/agent-shell-tests.el @@ -1891,10 +1891,10 @@ and rejects `new-deferred' and other unknown values." :type 'user-error)) (ert-deftest agent-shell--filter-session-prompt-choices-nil () - "Test that nil filter passes all choices through unchanged." - (let ((agent-shell-session-prompt-choices nil) + "Test that nil exclusion passes all choices through unchanged." + (let ((agent-shell-session-prompt-exclude-choices nil) (choices '(((:kind . :new-shell) - (:label . "Start new shell") + (:label . "New shell") (:value . nil)) ((:kind . :downloads-shell) (:label . "New Downloads shell") @@ -1911,12 +1911,13 @@ and rejects `new-deferred' and other unknown values." (should (equal (agent-shell--filter-session-prompt-choices choices) choices)))) -(ert-deftest agent-shell--filter-session-prompt-choices-list () - "Test that a list of kinds keeps only choices with matching kind." - (let ((agent-shell-session-prompt-choices '(:new-shell :acp-session))) +(ert-deftest agent-shell--filter-session-prompt-choices-exclude () + "Test that an exclusion list drops choices with matching kind." + (let ((agent-shell-session-prompt-exclude-choices + '(:downloads-shell :temp-shell :other-shell))) (should (equal (agent-shell--filter-session-prompt-choices '(((:kind . :new-shell) - (:label . "Start new shell") + (:label . "New shell") (:value . nil)) ((:kind . :downloads-shell) (:label . "New Downloads shell") @@ -1931,7 +1932,7 @@ and rejects `new-deferred' and other unknown values." (:label . "Session A") (:value . session-a)))) '(((:kind . :new-shell) - (:label . "Start new shell") + (:label . "New shell") (:value . nil)) ((:kind . :acp-session) (:label . "Session A")