diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-27 20:49:23 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-27 20:49:23 -0500 |
| commit | fa924acccc2e85bc39433cae608dcc9292795ed2 (patch) | |
| tree | ea45ee899bf152620f0d7f464bd84ede90661a2d /modules | |
| parent | 7833fb8bc0e3f9ece01ab2fe6fe07ded0efc4af4 (diff) | |
| download | dotemacs-fa924acccc2e85bc39433cae608dcc9292795ed2.tar.gz dotemacs-fa924acccc2e85bc39433cae608dcc9292795ed2.zip | |
feat(ai): remember the AI-Assistant panel width across toggles
The *AI-Assistant* side window always opened at a fixed 0.4 width, so resizing it by hand was lost the next time it opened. Now the F-key toggle captures the panel's width when it closes and reopens at that width for the rest of the session, the same way the music playlist remembers its height.
The panel has three entry points that all open the same buffer: the toggle, loading a saved conversation, and escalating a quick-ask. I gave them one shared remembered-width var (cj/--ai-assistant-width, owned by ai-config; the other two forward-declare it to avoid a circular require), so the panel comes back at one consistent width whichever door opens it. Capture lives only in the toggle's close path; the other two just replay.
One latent edge: ai-conversations replays with its configurable side, which defaults to right. If that's ever set to top or bottom, the remembered width fraction would land as a height. It can't happen at the default, so I left it as a known edge rather than complicating the call now.
The escalation test needed a top-level defvar for the shared var: a value-less defvar in the module is only file-local to the byte-compiler, so without it the function read the var dynamically and hit void when the test loaded ai-quick-ask without ai-config. ai-quick-ask 13/13 and ai-conversations 47/47 green.
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/ai-config.el | 28 | ||||
| -rw-r--r-- | modules/ai-conversations.el | 13 | ||||
| -rw-r--r-- | modules/ai-quick-ask.el | 12 |
3 files changed, 42 insertions, 11 deletions
diff --git a/modules/ai-config.el b/modules/ai-config.el index 199f644b..e439ab5c 100644 --- a/modules/ai-config.el +++ b/modules/ai-config.el @@ -40,6 +40,7 @@ (require 'keybindings) ;; provides cj/custom-keymap (require 'system-lib) ;; provides cj/auth-source-secret-value +(require 'cj-window-toggle-lib) ;; side-window size memory for the panel (autoload 'cj/gptel-save-conversation "ai-conversations" "Save the AI conversation to a file." t) (autoload 'cj/gptel-load-conversation "ai-conversations" "Load a saved AI conversation." t) @@ -413,14 +414,30 @@ Works for any buffer, whether it's visiting a file or not." ;;; ---------------------------- Toggle GPTel Window ---------------------------- +(defvar cj/ai-assistant-window-width 0.4 + "Default fraction of frame width for the *AI-Assistant* side window. +Used until the panel is resized and toggled off this session; after that, +the toggled-off width is remembered in `cj/--ai-assistant-width'.") + +(defvar cj/--ai-assistant-width nil + "Last width fraction the *AI-Assistant* side window was toggled off at. +nil falls back to `cj/ai-assistant-window-width'. Shared by the panel's +entry points (toggle, load-conversation, quick-ask escalation) so the +panel reopens at one consistent width. In-memory only -- resets each +Emacs session.") + (defun cj/toggle-gptel () - "Toggle the visibility of the AI-Assistant buffer, and place point at its end." + "Toggle the visibility of the AI-Assistant buffer, and place point at its end. +The panel opens at `cj/ai-assistant-window-width'; once it has been resized +and toggled off this session, it reopens at that remembered width." (interactive) (let* ((buf-name "*AI-Assistant*") (buffer (get-buffer buf-name)) (win (and buffer (get-buffer-window buffer)))) (if win - (delete-window win) + (progn + (cj/side-window-capture-size win 'right 'cj/--ai-assistant-width) + (delete-window win)) ;; Ensure GPTel and our backends are initialized before creating the buffer (unless (featurep 'gptel) (require 'gptel)) @@ -430,10 +447,9 @@ Works for any buffer, whether it's visiting a file or not." (gptel buf-name gptel-backend)) (setq buffer (get-buffer buf-name)) (setq win - (display-buffer-in-side-window - buffer - '((side . right) - (window-width . 0.4)))) + (cj/side-window-display + buffer 'right 'cj/--ai-assistant-width + cj/ai-assistant-window-width)) (select-window win) (with-current-buffer buffer (goto-char (point-max)))))) diff --git a/modules/ai-conversations.el b/modules/ai-conversations.el index fc234a82..839af9ad 100644 --- a/modules/ai-conversations.el +++ b/modules/ai-conversations.el @@ -13,6 +13,13 @@ ;;; Code: +(require 'cj-window-toggle-lib) ;; cj/side-window-display + +;; Shared *AI-Assistant* remembered-width state, owned by ai-config.el. +;; Forward-declared so loading a conversation reopens the panel at the same +;; width as the F-key toggle without a circular require. +(defvar cj/--ai-assistant-width) + (defgroup cj/ai-conversations nil "Conversation persistence for GPTel (save/load/delete, autosave)." :group 'gptel @@ -344,9 +351,9 @@ enable autosave." (cj/gptel--autosave-start-timer)) (let ((buf (get-buffer "*AI-Assistant*"))) (unless (get-buffer-window buf) - (display-buffer-in-side-window - buf `((side . ,cj/gptel-conversations-window-side) - (window-width . ,cj/gptel-conversations-window-width))))) + (cj/side-window-display + buf cj/gptel-conversations-window-side + 'cj/--ai-assistant-width cj/gptel-conversations-window-width))) (select-window (get-buffer-window "*AI-Assistant*")) (message "Loaded conversation from: %s" filepath)))) diff --git a/modules/ai-quick-ask.el b/modules/ai-quick-ask.el index 0d56be8c..16f3afae 100644 --- a/modules/ai-quick-ask.el +++ b/modules/ai-quick-ask.el @@ -15,6 +15,14 @@ ;;; Code: +(require 'cj-window-toggle-lib) ;; cj/side-window-display + +;; Shared *AI-Assistant* panel-width state, owned by ai-config.el. Forward- +;; declared here so the escalation reopens the panel at the same remembered +;; width as the F-key toggle without a circular require. +(defvar cj/ai-assistant-window-width) +(defvar cj/--ai-assistant-width) + (defvar-local cj/gptel-quick--prompt nil "Buffer-local: the prompt used for the current *GPTel-Quick* session.") @@ -125,8 +133,8 @@ side window, then dismisses the quick buffer." (with-current-buffer ai-buf (goto-char (point-max)) (insert seed)) - (display-buffer-in-side-window - ai-buf '((side . right) (window-width . 0.4))) + (cj/side-window-display + ai-buf 'right 'cj/--ai-assistant-width cj/ai-assistant-window-width) (cj/gptel-quick-dismiss)))) (provide 'ai-quick-ask) |
