branch: elpa/aidermacs
commit 89bfe7d4de2b16b63882631fae1322a05f383a81
Author: Mingde (Matthew) Zeng <[email protected]>
Commit: Mingde (Matthew) Zeng <[email protected]>
Refactor and unify aidermacs--send-command
Partially revert #21 to pave ways for diff tracking
---
aidermacs-backends.el | 18 ++++------
aidermacs-models.el | 9 +++--
aidermacs.el | 93 +++++++++++++++++++++++++++++++++------------------
3 files changed, 71 insertions(+), 49 deletions(-)
diff --git a/aidermacs-backends.el b/aidermacs-backends.el
index beabf982af..86a99dffc1 100644
--- a/aidermacs-backends.el
+++ b/aidermacs-backends.el
@@ -182,25 +182,19 @@ and is using either comint or vterm mode."
(and (fboundp 'vterm-mode)
(derived-mode-p 'vterm-mode)))))))
-(defun aidermacs--send-command-backend (buffer command)
- "Send command to buffer using the appropriate backend.
-BUFFER is the target buffer. COMMAND is the text to send."
- (setq aidermacs--last-command command
- aidermacs--current-output nil)
- (if (eq aidermacs-backend 'vterm)
- (aidermacs--send-command-vterm buffer command)
- (aidermacs--send-command-comint buffer command)))
-
-(defun aidermacs--send-command-redirect-backend (buffer command &optional
callback)
+(defun aidermacs--send-command-backend (buffer command &optional redirect
callback)
"Send command to buffer using the appropriate backend.
BUFFER is the target buffer. COMMAND is the text to send.
-CALLBACK if provided will be called with the command output when available."
+If REDIRECT is non-nil it redirects the output (hidden) for comint backend.
+If CALLBACK is non-nil it will be called after the command finishes."
(setq aidermacs--last-command command
aidermacs--current-output nil
aidermacs--current-callback callback)
(if (eq aidermacs-backend 'vterm)
(aidermacs--send-command-vterm buffer command)
- (aidermacs--send-command-redirect-comint buffer command)))
+ (if redirect
+ (aidermacs--send-command-redirect-comint buffer command)
+ (aidermacs--send-command-comint buffer command))))
(provide 'aidermacs-backends)
diff --git a/aidermacs-models.el b/aidermacs-models.el
index 888cf02b9f..a5b19f67be 100644
--- a/aidermacs-models.el
+++ b/aidermacs-models.el
@@ -26,8 +26,7 @@
(require 'json)
(require 'url)
-(declare-function aidermacs--send-command "aidermacs" (command &optional
switch-to-buffer))
-(declare-function aidermacs--send-command-redirect "aidermacs" (command
callback))
+(declare-function aidermacs--send-command "aidermacs" (command &optional
no-switch-to-buffer use-existing redirect callback))
(declare-function aidermacs-buffer-name "aidermacs" ())
(declare-function aidermacs-exit "aidermacs" ())
@@ -126,14 +125,14 @@ This is a private function used internally."
(condition-case nil
(let ((model (completing-read "Select AI model: "
aidermacs--cached-models nil t)))
(when model
- (aidermacs--send-command (format "/model %s" model) t)))
+ (aidermacs--send-command (format "/model %s" model))))
(quit (message "Model selection cancelled"))))
(defun aidermacs--get-available-models ()
"Get list of models supported by aider using the /models command.
This fetches models from various API providers and caches them."
- (aidermacs--send-command-redirect
- "/models /"
+ (aidermacs--send-command
+ "/models /" nil nil t
(lambda ()
(let* ((supported-models
(seq-filter
diff --git a/aidermacs.el b/aidermacs.el
index 1fde7caab6..34df1dc94a 100644
--- a/aidermacs.el
+++ b/aidermacs.el
@@ -314,17 +314,37 @@ If USE-EXISTING is non-nil, use an existing buffer
instead of creating new."
(when (and switch-to-buffer (not (string= (buffer-name) buffer-name)))
(aidermacs-switch-to-buffer buffer-name))))
-(defun aidermacs--send-command-redirect (command callback &optional
use-existing)
- "Send command to the corresponding aidermacs process in the background.
+(defun aidermacs--is-edit-command-p (command buffer)
+ "Determine if COMMAND might result in code edits based on current mode in
BUFFER.
+Returns non-nil if the command is a direct edit command or if we're in a mode
+that allows edits and the command isn't explicitly a non-edit command."
+ (with-current-buffer buffer
+ (or
+ ;; Explicit edit commands always trigger edit tracking
+ (string-match-p "^\\(/code\\|/architect\\)" command)
+
+ ;; In code or architect mode, any message that's not a command could edit
code
+ (and (memq aidermacs--current-mode '(code architect))
+ (not (string-prefix-p "/" command))))))
+
+(defun aidermacs--send-command (command &optional no-switch-to-buffer
use-existing redirect callback)
+ "Send command to the corresponding aidermacs process.
COMMAND is the text to send.
-CALLBACK will be called with the command output when available.
-If USE-EXISTING is non-nil, use an existing buffer instead of creating new."
+If NO-SWITCH-TO-BUFFER is non-nil, don't switch to the aidermacs buffer.
+If USE-EXISTING is non-nil, use an existing buffer instead of creating new.
+If REDIRECT is non-nil it redirects the output (hidden) for comint backend.
+If CALLBACK is non-nil it will be called after the command finishes."
(let* ((buffer-name (aidermacs-get-buffer-name use-existing))
(buffer (or (get-buffer buffer-name)
(progn (aidermacs-run)
(get-buffer buffer-name))))
(processed-command (aidermacs--process-message-if-multi-line
command)))
- (aidermacs--send-command-redirect-backend buffer processed-command
callback)))
+
+ (if (aidermacs--is-edit-command-p command buffer)
+ (aidermacs--send-command-with-edit-tracking processed-command
no-switch-to-buffer use-existing)
+ (aidermacs--send-command-backend buffer processed-command redirect
callback))
+ (when (and (not no-switch-to-buffer) (not (string= (buffer-name)
buffer-name)))
+ (aidermacs-switch-to-buffer buffer-name))))
;;;###autoload
(defun aidermacs-switch-to-buffer (&optional buffer-name)
@@ -362,7 +382,7 @@ If the current buffer is already the aidermacs buffer, do
nothing."
(defun aidermacs-exit ()
"Send the command \"/exit\" to the aidermacs buffer."
(interactive)
- (aidermacs--send-command "/exit"))
+ (aidermacs--send-command "/exit" t))
(defun aidermacs--process-message-if-multi-line (str)
@@ -405,14 +425,14 @@ The full command will be \"COMMAND-PREFIX <current buffer
file full path>\"."
(interactive)
(let ((command (aidermacs-read-string "Enter general aider command: ")))
;; Use the shared helper function to send the command
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
;;;###autoload
(defun aidermacs-direct-change ()
"Prompt the user for an input and send it to aidemracs prefixed with \"/code
\"."
(interactive)
(when-let ((command (aidermacs--form-prompt "/code" nil t "empty to change
to code mode")))
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
(defun aidermacs--parse-ls-output (output)
"Parse the /ls command output to extract files in chat.
@@ -455,6 +475,14 @@ Returns a deduplicated list of such file names."
(setq aidermacs--tracked-files (delete-dups (nreverse files)))
aidermacs--tracked-files))))
+(defun aidermacs--get-files-in-session (callback)
+ "Get list of files in current session and call CALLBACK with the result."
+ (aidermacs--send-command
+ "/ls" nil t
+ (lambda ()
+ (let ((files (aidermacs--parse-ls-output aidermacs--current-output)))
+ (funcall callback files)))))
+
;;;###autoload
(defun aidermacs-list-added-files ()
"List all files currently added to the chat session.
@@ -526,41 +554,41 @@ If called from the aidermacs buffer, use general question
instead."
(call-interactively #'aidermacs-general-question)
(when-let ((command (aidermacs--form-prompt "/ask" "Question")))
(aidermacs-add-current-file)
- (aidermacs--send-command command t))))
+ (aidermacs--send-command command))))
;;;###autoload
(defun aidermacs-general-question ()
"Prompt the user for a general question without code context."
(interactive)
(when-let ((command (aidermacs--form-prompt "/ask" nil t "empty to change to
ask mode")))
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
;;;###autoload
(defun aidermacs-help ()
"Prompt the user for an input prefixed with \"/help \"."
(interactive)
(when-let ((command (aidermacs--form-prompt "/help" nil t "empty for general
/help")))
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
;;;###autoload
(defun aidermacs-general-architect ()
"Prompt the user for an input prefixed with \"/architect \"."
(interactive)
(when-let ((command (aidermacs--form-prompt "/architect" nil t "empty to
change to architect mode")))
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
;;;###autoload
(defun aidermacs-debug-exception ()
"Prompt the user for an input and send it to aidemracs prefixed with
\"/debug \"."
(interactive)
(when-let ((command (aidermacs--form-prompt "/ask" "Debug exception")))
- (aidermacs--send-command command t)))
+ (aidermacs--send-command command)))
;;;###autoload
(defun aidermacs-accept-change ()
"Send the command \"go ahead\" to the aidemracs."
(interactive)
- (aidermacs--send-command "/code go ahead" t))
+ (aidermacs--send-command "/code go ahead"))
;;;###autoload
@@ -608,7 +636,7 @@ If point is in a function, inspect that function."
(call-interactively #'aidermacs-general-architect)
(when-let ((command (aidermacs--form-prompt "/architect" "Architect")))
(aidermacs-add-current-file)
- (aidermacs--send-command command t))))
+ (aidermacs--send-command command))))
;;;###autoload
(defun aidermacs-question-this-symbol ()
@@ -623,14 +651,14 @@ If point is in a function, inspect that function."
(if symbol
(progn
(aidermacs-add-current-file)
- (aidermacs--send-command prompt t))
+ (aidermacs--send-command prompt))
(error "No symbol under point!"))))
(defun aidermacs-send-command-with-prefix (prefix command)
"Send COMMAND to the aidermacs buffer with PREFIX.
PREFIX is the text to prepend. COMMAND is the text to send."
(aidermacs-add-current-file)
- (aidermacs--send-command (concat prefix command) t))
+ (aidermacs--send-command (concat prefix command)))
(defun aidermacs--add-files-helper (files read-only &optional message)
"Helper function to add files with read-only flag.
@@ -640,8 +668,9 @@ as read-only. Optional MESSAGE can override the default
success message."
(files (delq nil files)))
(if files
(progn
- (aidermacs--send-command (format "%s %s" cmd
- (mapconcat #'identity files " ")) t)
+ (aidermacs--send-command
+ (format "%s %s" cmd
+ (mapconcat #'identity files " ")))
(message (or message
(format "Added %d files as %s"
(length files)
@@ -755,7 +784,7 @@ Otherwise:
function-name))
(command (aidermacs--form-prompt "/architect"
initial-input)))
(aidermacs-add-current-file)
- (aidermacs--send-command command t))
+ (aidermacs--send-command command))
(message "Current function '%s' does not appear to be a test
function." function-name))
(message "Please place cursor inside a test function to
implement.")))
;; Non-test file case
@@ -769,7 +798,7 @@ Otherwise:
(file-name-nondirectory buffer-file-name)
common-instructions)))
(command (aidermacs--form-prompt "/architect" initial-input)))
(aidermacs-add-current-file)
- (aidermacs--send-command command t)))))))
+ (aidermacs--send-command command)))))))
;;;###autoload
(defun aidermacs-fix-failing-test-under-cursor ()
@@ -781,7 +810,7 @@ This function assumes the cursor is on or inside a test
function."
test-function-name))
(command (aidermacs--form-prompt "/architect" initial-input)))
(aidermacs-add-current-file)
- (aidermacs--send-command command t))
+ (aidermacs--send-command command))
(message "No test function found at cursor position.")))
(defun aidermacs-create-session-scratchpad ()
@@ -799,7 +828,7 @@ Use this to add functions, code snippets, or other content
to the session."
(insert ";; Add your code snippets, functions, or other content here\n")
(insert ";; Just edit and save - changes will be available to aider\n\n")
(write-file filename))
- (aidermacs--send-command (format "/read %s" filename) t)
+ (aidermacs--send-command (format "/read %s" filename))
(find-file-other-window filename)
(message "Created and added scratchpad to session: %s" filename)))
@@ -815,7 +844,7 @@ This allows you to add the file's content to a specific
session."
nil nil t initial))))
(if (not (file-exists-p file))
(message "File does not exist: %s" file)
- (aidermacs--send-command (format "/read %s" file) t t))))
+ (aidermacs--send-command (format "/read %s" file) nil t))))
(defun aidermacs--is-comment-line (line)
"Check if LINE is a comment line based on current buffer's comment syntax.
@@ -847,7 +876,7 @@ Otherwise implement TODOs for the entire current file."
(format " on this comment: `%s`."
current-line))
" Keep existing code structure"))))
(aidermacs-add-current-file)
- (aidermacs--send-command command t)))))
+ (aidermacs--send-command command)))))
;;;###autoload
(defun aidermacs-send-line-or-region ()
@@ -859,7 +888,7 @@ Otherwise, send the line under cursor."
(buffer-substring-no-properties (region-beginning)
(region-end))
(string-trim (thing-at-point 'line t)))))
(when text
- (aidermacs--send-command text t))))
+ (aidermacs--send-command text))))
;;;###autoload
(defun aidermacs-send-region-by-line ()
@@ -871,7 +900,7 @@ Otherwise, send the line under cursor."
(mapc (lambda (line)
(let ((trimmed (string-trim line)))
(when (not (string-empty-p trimmed))
- (aidermacs--send-command trimmed t))))
+ (aidermacs--send-command trimmed))))
lines))
(message "No region selected.")))
@@ -888,7 +917,7 @@ When sending paragraph content, preserve cursor position."
(buffer-substring-no-properties (region-beginning)
(region-end))
(deactivate-mark))))))
(when text
- (aidermacs--send-command text t))))
+ (aidermacs--send-command text))))
;;;###autoload
(defun aidermacs-open-prompt-file ()
@@ -973,7 +1002,7 @@ prompt files and other Aider-related files:
"Switch aider to code mode.
In code mode, aider will make changes to your code to satisfy your requests."
(interactive)
- (aidermacs--send-command "/chat-mode code" t)
+ (aidermacs--send-command "/chat-mode code")
(with-current-buffer (get-buffer (aidermacs-get-buffer-name))
(setq-local aidermacs--current-mode 'code))
(message "Switched to code mode <default> - aider will make changes to your
code"))
@@ -983,7 +1012,7 @@ In code mode, aider will make changes to your code to
satisfy your requests."
"Switch aider to ask mode.
In ask mode, aider will answer questions about your code, but never edit it."
(interactive)
- (aidermacs--send-command "/chat-mode ask" t)
+ (aidermacs--send-command "/chat-mode ask")
(with-current-buffer (get-buffer (aidermacs-get-buffer-name))
(setq-local aidermacs--current-mode 'ask))
(message "Switched to ask mode - you can chat freely, aider will not edit
your code"))
@@ -994,7 +1023,7 @@ In ask mode, aider will answer questions about your code,
but never edit it."
In architect mode, aider will first propose a solution, then ask if you want
it to turn that proposal into edits to your files."
(interactive)
- (aidermacs--send-command "/chat-mode architect" t)
+ (aidermacs--send-command "/chat-mode architect")
(with-current-buffer (get-buffer (aidermacs-get-buffer-name))
(setq-local aidermacs--current-mode 'architect))
(message "Switched to architect mode - aider will propose solutions before
making changes"))
@@ -1005,7 +1034,7 @@ it to turn that proposal into edits to your files."
In help mode, aider will answer questions about using aider, configuring,
troubleshooting, etc."
(interactive)
- (aidermacs--send-command "/chat-mode help" t)
+ (aidermacs--send-command "/chat-mode help")
(with-current-buffer (get-buffer (aidermacs-get-buffer-name))
(setq-local aidermacs--current-mode 'help))
(message "Switched to help mode - aider will answer questions about using
aider"))