branch: elpa/aidermacs commit a1282c8134c898389544e668e64f1c6334d3eb73 Author: Mingde (Matthew) Zeng <matthew...@posteo.net> Commit: Mingde (Matthew) Zeng (aider) <matthew...@posteo.net>
feat: Add vterm backend support and split aider-run-aider into backend-specific functions --- aider.el | 121 +++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 27 deletions(-) diff --git a/aider.el b/aider.el index 43f3880003..68200e5097 100644 --- a/aider.el +++ b/aider.el @@ -227,17 +227,31 @@ If not in a git repository and no buffer file exists, an error is raised." (t (error "Not in a git repository and current buffer is not associated with a file"))))) -;;;###autoload -(defun aider-run-aider (&optional edit-args) +;; 1. Add a new customizable variable to choose the backend. +(defcustom aider-backend 'comint + "Backend to use for the aider process. +Options are 'comint (the default) or 'vterm. When set to 'vterm, aider will +launch a fully functional vterm buffer (with bracketed paste support) instead +of using a comint process." + :type '(choice (const :tag "Comint" comint) + (const :tag "VTerm" vterm)) + :group 'aider) + +;; Optionally, you can require vterm if the user selects it: +(when (and (eq aider-backend 'vterm) (not (featurep 'vterm))) + (require 'vterm nil t)) + +;; 2. Split the aider-run-aider function into two versions. +;; (a) The original comint version (renamed to aider-run-aider-comint) +(defun aider-run-aider-comint (&optional edit-args) "Create a comint-based buffer and run \"aider\" for interactive conversation. With the universal argument, prompt to edit aider-args before running." (interactive "P") (let* ((buffer-name (aider-buffer-name)) (comint-terminfo-terminal "dumb") (current-args (if edit-args - (split-string - (read-string "Edit aider arguments: " - (mapconcat 'identity aider-args " "))) + (split-string (read-string "Edit aider arguments: " + (mapconcat 'identity aider-args " "))) aider-args)) (source-buffer (window-buffer (selected-window)))) (unless (comint-check-proc buffer-name) @@ -256,6 +270,81 @@ With the universal argument, prompt to edit aider-args before running." (font-lock-add-keywords nil aider-font-lock-keywords t))) (aider-switch-to-buffer))) +(defun aider-run-aider-vterm (&optional edit-args) + "Create a vterm-based buffer and run \"aider\" for interactive conversation using vterm. +With the universal argument, prompt to edit aider-args before running. + +This uses the vterm backend (which supports bracketed paste and a full TUI) +by temporarily binding `vterm-shell' and `vterm-buffer-name'." + (interactive "P") + (unless (require 'vterm nil t) + (error "vterm package is not available")) + (let* ((buffer-name (aider-buffer-name)) + (current-args (if edit-args + (split-string (read-string "Edit aider arguments: " + (mapconcat 'identity aider-args " "))) + aider-args)) + ;; Build the full command line to run aider. + (cmd (concat aider-program " " (mapconcat 'identity current-args " "))) + (source-buffer (window-buffer (selected-window)))) + (unless (get-buffer buffer-name) + (let ((vterm-shell cmd) + (vterm-buffer-name buffer-name)) + (vterm) + (with-current-buffer buffer-name + (setq-local aider-backend 'vterm) + ;; (Optionally, enable aider-minor-mode to inherit keybindings) + (aider-minor-mode 1)))) + (aider-switch-to-buffer))) + +;;;###autoload +(defun aider-run-aider (&optional edit-args) + "Run aider process using the selected backend. +With the universal argument, prompt to edit aider-args before running. +Dispatches to the vterm version when `aider-backend' is 'vterm, and to the +comint version otherwise." + (interactive "P") + (if (eq aider-backend 'vterm) + (aider-run-aider-vterm edit-args) + (aider-run-aider-comint edit-args))) + +(defun aider--send-command-comint (command &optional switch-to-buffer) + "Send COMMAND to the aider comint buffer after performing necessary checks. +COMMAND should be a string representing the command to send." + (if-let ((aider-buffer (get-buffer (aider-buffer-name)))) + (let* ((command (aider--process-message-if-multi-line command)) + (aider-process (get-buffer-process aider-buffer))) + (if (and aider-process (comint-check-proc aider-buffer)) + (progn + (aider-reset-font-lock-state) + (aider--comint-send-string-syntax-highlight aider-buffer (concat command "\n")) + (when switch-to-buffer + (aider-switch-to-buffer)) + (sleep-for 0.2)) + (message "No active process found in buffer %s." (aider-buffer-name)))) + (message "Buffer %s does not exist. Please start 'aider' first." (aider-buffer-name)))) + +(defun aider--send-command-vterm (command &optional switch-to-buffer) + "Send COMMAND to the aider vterm buffer. +COMMAND should be a string. If SWITCH-TO-BUFFER is non-nil, switch to the aider buffer. +This uses `vterm-send-string' and `vterm-send-return' to simulate input." + (if-let ((aider-buffer (get-buffer (aider-buffer-name)))) + (with-current-buffer aider-buffer + (let ((processed-command (aider--process-message-if-multi-line command))) + (vterm-send-string processed-command) + (vterm-send-return) + (when switch-to-buffer + (aider-switch-to-buffer)) + (sleep-for 0.2))) + (message "Buffer %s does not exist. Please start 'aider' first." (aider-buffer-name)))) + +(defun aider--send-command (command &optional switch-to-buffer) + "Send COMMAND to the corresponding aider process after performing necessary checks. +Dispatches to the appropriate backend (comint or vterm) based on `aider-backend`." + (if (eq aider-backend 'vterm) + (aider--send-command-vterm command switch-to-buffer) + (aider--send-command-comint command switch-to-buffer))) + (defun aider-kill-buffer () "Clean-up fontify buffer." (when (bufferp aider--font-lock-buffer) @@ -497,28 +586,6 @@ wrap it in {aider\\nstr\\naider}. Otherwise return STR unchanged." (format "{aider\n%s\naider}" str) str)) -;; Shared helper function to send commands to corresponding aider buffer -(defun aider--send-command (command &optional switch-to-buffer) - "Send COMMAND to the corresponding aider comint buffer after performing necessary checks. -COMMAND should be a string representing the command to send." - ;; Check if the corresponding aider buffer exists - (if-let ((aider-buffer (get-buffer (aider-buffer-name)))) - (let* ((command (aider--process-message-if-multi-line command)) - (aider-process (get-buffer-process aider-buffer))) - ;; Check if the corresponding aider buffer has an active process - (if (and aider-process (comint-check-proc aider-buffer)) - (progn - (aider-reset-font-lock-state) - ;; Send the command to the aider process - (aider--comint-send-string-syntax-highlight aider-buffer (concat command "\n")) - ;; Provide feedback to the user - ;; (message "Sent command to aider buffer: %s" (string-trim command)) - (when switch-to-buffer - (aider-switch-to-buffer)) - (sleep-for 0.2)) - (message "No active process found in buffer %s." (aider-buffer-name)))) - (message "Buffer %s does not exist. Please start 'aider' first." (aider-buffer-name)))) - ;;;###autoload (defun aider-add-or-read-current-file (command-prefix) "Send the command \"COMMAND-PREFIX <current buffer file full path>\" to the corresponding aider comint buffer."