branch: elpa/aidermacs commit 0e828efdd8c7ef0a4d88444747db77e67a5577d4 Author: Mingde (Matthew) Zeng (aider) <matthew...@posteo.net> Commit: Mingde (Matthew) Zeng <matthew...@posteo.net>
feat: Add file listing functionality to Aidermacs session management --- aidermacs-backend-comint.el | 11 +++--- aidermacs-backend-vterm.el | 9 ++--- aidermacs-backends.el | 24 +++++-------- aidermacs.el | 86 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 44 deletions(-) diff --git a/aidermacs-backend-comint.el b/aidermacs-backend-comint.el index c157e01bf7..d170ddcabc 100644 --- a/aidermacs-backend-comint.el +++ b/aidermacs-backend-comint.el @@ -216,7 +216,7 @@ This allows for multi-line input without sending the command." (kill-buffer aidermacs--syntax-work-buffer))) (defvar-local aidermacs--comint-output-temp "" - "Temporary output variable storing the output log.") + "Temporary output variable storing the raw output string.") (defun aidermacs-input-sender (proc string) "Reset font-lock state before executing a command." @@ -224,10 +224,10 @@ This allows for multi-line input without sending the command." (comint-simple-send proc (aidermacs--process-message-if-multi-line string))) (defun aidermacs--comint-output-filter (output) - "Accumulate OUTPUT until a prompt is detected, then store it." + "Accumulate OUTPUT string until a prompt is detected, then store it." (unless (string-empty-p output) (setq aidermacs--comint-output-temp - (concat aidermacs--comint-output-temp output)) + (concat aidermacs--comint-output-temp (substring-no-properties output))) ;; Check if the output contains a prompt (when (string-match-p "\n[^[:space:]]*>[[:space:]]$" aidermacs--comint-output-temp) (aidermacs--store-output aidermacs--comint-output-temp) @@ -252,9 +252,8 @@ This allows for multi-line input without sending the command." (use-local-map local-map)) (font-lock-add-keywords nil aidermacs-font-lock-keywords t))))) -(defun aidermacs--send-command-comint (buffer command &optional switch-to-buffer) - "Send COMMAND to the aidermacs comint BUFFER. -If SWITCH-TO-BUFFER is non-nil, switch to the buffer after sending." +(defun aidermacs--send-command-comint (buffer command) + "Send COMMAND to the aidermacs comint BUFFER." (with-current-buffer buffer (let ((process (get-buffer-process buffer)) (inhibit-read-only t)) diff --git a/aidermacs-backend-vterm.el b/aidermacs-backend-vterm.el index 609e5c4ba2..b26825d1fd 100644 --- a/aidermacs-backend-vterm.el +++ b/aidermacs-backend-vterm.el @@ -80,17 +80,14 @@ and BUFFER-NAME is the name of the vterm buffer." (setq vterm-shell vterm-shell-orig))) buffer-name) -(defun aidermacs--send-command-vterm (buffer command &optional switch-to-buffer) - "Send COMMAND to the aidermacs vterm BUFFER. -If SWITCH-TO-BUFFER is non-nil, switch to BUFFER after sending the command." +(defun aidermacs--send-command-vterm (buffer command) + "Send COMMAND to the aidermacs vterm BUFFER." (with-current-buffer buffer ;; Store command before sending (setq aidermacs--last-command command aidermacs--current-output nil) (vterm-send-string command) - (vterm-send-return) - (when switch-to-buffer - (switch-to-buffer buffer)))) + (vterm-send-return))) (provide 'aidermacs-backend-vterm) diff --git a/aidermacs-backends.el b/aidermacs-backends.el index 3534d79fbf..3914c07a78 100644 --- a/aidermacs-backends.el +++ b/aidermacs-backends.el @@ -39,8 +39,8 @@ Each entry is a cons cell (timestamp . output-text).") (defvar aidermacs--last-command nil "Store the last command sent to aidermacs.") -(defvar aidermacs--current-output nil - "Accumulator for current output being captured.") +(defvar aidermacs--current-output "" + "Accumulator for current output being captured as a string.") (defun aidermacs-get-output-history (&optional limit) "Get the output history, optionally limited to LIMIT entries. @@ -50,20 +50,15 @@ Returns a list of (timestamp . output-text) pairs, most recent first." (seq-take history limit) history))) -(defun aidermacs-get-last-output () - "Get the most recent output from aidermacs." - (interactive) - (message aidermacs--current-output)) - (defun aidermacs-clear-output-history () "Clear the output history." (interactive) (setq aidermacs--output-history nil)) (defun aidermacs--store-output (output) - "Store OUTPUT in the history with timestamp." - (setq aidermacs--current-output output) - (push (cons (current-time) output) aidermacs--output-history) + "Store OUTPUT string in the history with timestamp." + (setq aidermacs--current-output (substring-no-properties output)) + (push (cons (current-time) (substring-no-properties output)) aidermacs--output-history) (when (> (length aidermacs--output-history) aidermacs-output-limit) (setq aidermacs--output-history (seq-take aidermacs--output-history aidermacs-output-limit)))) @@ -79,14 +74,13 @@ and BUFFER-NAME is the name for the aidermacs buffer." (t (aidermacs-run-aidermacs-comint program args buffer-name)))) -(defun aidermacs--send-command-backend (buffer command &optional switch-to-buffer) - "Send COMMAND to BUFFER using the appropriate backend. -If SWITCH-TO-BUFFER is non-nil, switch to the buffer after sending." +(defun aidermacs--send-command-backend (buffer command) + "Send COMMAND to BUFFER using the appropriate backend." (cond ((eq aidermacs-backend 'vterm) - (aidermacs--send-command-vterm buffer command switch-to-buffer)) + (aidermacs--send-command-vterm buffer command)) (t - (aidermacs--send-command-comint buffer command switch-to-buffer)))) + (aidermacs--send-command-comint buffer command)))) (provide 'aidermacs-backends) diff --git a/aidermacs.el b/aidermacs.el index 33702ae74a..9ff7e78d70 100644 --- a/aidermacs.el +++ b/aidermacs.el @@ -169,7 +169,8 @@ Affects the system message too.") ("p" "Open Prompt File" aidermacs-open-prompt-file) ("h" "Help" aidermacs-help) ("H" "Show Output History" aidermacs-show-output-history) - ("C" "Copy Last Output" aidermacs-copy-last-output) + ("C" "Copy Last Output" aidermacs-get-last-output) + ("L" "List Files in Chat" aidermacs-list-added-files) ] ]) @@ -209,7 +210,7 @@ With the universal argument, prompt to edit aidermacs-args before running." Dispatches to the appropriate backend." (if-let ((aidermacs-buffer (get-buffer (aidermacs-buffer-name)))) (let ((processed-command (aidermacs--process-message-if-multi-line command))) - (aidermacs--send-command-backend aidermacs-buffer processed-command switch-to-buffer) + (aidermacs--send-command-backend aidermacs-buffer processed-command) (when switch-to-buffer (aidermacs-switch-to-buffer)) (sleep-for 0.2)) @@ -221,15 +222,21 @@ Dispatches to the appropriate backend." (defun aidermacs-switch-to-buffer () "Switch to the aidermacs buffer. When `aidermacs--switch-to-buffer-other-frame' is non-nil, open in a new frame. +If the buffer is already visible in a window, switch to that window. If the current buffer is already the aidermacs buffer, do nothing." (interactive) - (if (string= (buffer-name) (aidermacs-buffer-name)) - (message "Already in aidermacs buffer") - (if-let ((buffer (get-buffer (aidermacs-buffer-name)))) - (if aidermacs--switch-to-buffer-other-frame - (switch-to-buffer-other-frame buffer) - (pop-to-buffer buffer)) - (message "Buffer '%s' does not exist." (aidermacs-buffer-name))))) + (let ((buffer (get-buffer (aidermacs-buffer-name)))) + (cond + ((string= (buffer-name) (aidermacs-buffer-name)) + (message "Already in aidermacs buffer")) + ((and buffer (get-buffer-window buffer)) + (select-window (get-buffer-window buffer))) ;; Switch to existing window + (buffer + (if aidermacs--switch-to-buffer-other-frame + (switch-to-buffer-other-frame buffer) + (pop-to-buffer buffer))) + (t + (message "Buffer '%s' does not exist." (aidermacs-buffer-name)))))) ;; Function to reset the aidermacs buffer ;;;###autoload @@ -322,6 +329,54 @@ wrap it in {aidermacs\nstr\naidermacs}. Otherwise return STR unchanged." (let ((command (aidermacs-read-string "Enter code change requirement: "))) (aidermacs-send-command-with-prefix "/code " command))) +(defun aidermacs--parse-ls-output (output) + "Parse the /ls command OUTPUT to extract files in chat. + +After the \"Files in chat:\" header, each subsequent line that begins with +whitespace is processed. The first non-whitespace token is taken as the file name. +Relative paths are resolved using the repository root (if available) or +`default-directory`. Only files that exist on disk are included in the result. +Returns a deduplicated list of such file names." + (when output + (with-temp-buffer + (insert output) + (goto-char (point-min)) + (when (search-forward "Files in chat:" nil t) + ;; Skip header and any blank lines. + (forward-line 1) + (while (and (not (eobp)) + (string-empty-p (string-trim (thing-at-point 'line t)))) + (forward-line 1)) + (let ((base (or (vc-git-root default-directory) + default-directory)) + files) + ;; Process lines that start with whitespace. + (while (and (not (eobp)) + (string-match-p "^[[:space:]]" (thing-at-point 'line t))) + (let* ((line (string-trim (thing-at-point 'line t))) + (file (car (split-string line)))) + (unless (string-empty-p file) + (let ((file-abs (if (file-name-absolute-p file) + file + (expand-file-name file base)))) + (when (file-exists-p file-abs) + (push file files))))) + (forward-line 1)) + (delete-dups (nreverse files))))))) + +;;;###autoload +(defun aidermacs-list-added-files () + "List all files currently added to the chat session." + (interactive) + (aidermacs--send-command "/ls" t) + ;; Wait briefly for output to be processed + (sleep-for 0.5) + (if-let ((files (aidermacs--parse-ls-output aidermacs--current-output))) + (progn + (message "%s" (prin1-to-string files)) + files) + (message "No files currently in chat or unable to parse output"))) + ;;;###autoload (defun aidermacs-show-output-history () "Display the AI output history in a new buffer." @@ -343,15 +398,12 @@ wrap it in {aidermacs\nstr\naidermacs}. Otherwise return STR unchanged." (switch-to-buffer-other-frame buf)))) ;;;###autoload -(defun aidermacs-copy-last-output () - "Copy the most recent AI output to the kill ring." +(defun aidermacs-get-last-output () + "Get the most recent output from aidermacs." (interactive) - (if-let ((last-output (cdr (aidermacs-get-last-output)))) - (progn - (kill-new last-output) - (message "Copied last AI output to kill ring")) - (message "No AI output available"))) - + (message aidermacs--current-output) + (kill-new aidermacs--current-output) + aidermacs--current-output) ;; New function to get command from user and send it prefixed with "/ask "