branch: elpa/aidermacs
commit 89bfe7d4de2b16b63882631fae1322a05f383a81
Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
Commit: Mingde (Matthew) Zeng <matthew...@posteo.net>

    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"))

Reply via email to