branch: elpa/aidermacs
commit 73eda045ac57c97a71f78dbafbadc948d8f9ec57
Merge: 47918c434d 764a99dd5e
Author: Reindert-Jan Ekker <rjek...@gmail.com>
Commit: GitHub <nore...@github.com>

    Merge branch 'main' into match-theme
---
 .gitignore                  |   4 ++
 CHANGELOG.md                |  16 +++++
 README.md                   |  67 ++++++++++-------
 aidermacs-backend-comint.el |  15 +++-
 aidermacs-backend-vterm.el  |  18 +++--
 aidermacs-backends.el       | 171 +++++++++++++++++++++-----------------------
 aidermacs-models.el         |   6 +-
 aidermacs.el                |  56 +++++++++------
 8 files changed, 208 insertions(+), 145 deletions(-)

diff --git a/.gitignore b/.gitignore
index 7364d48a21..05d1193288 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,7 @@
 .env
 __pycache__
 /*.elc
+
+# ELPA-generated files.
+/aidermacs-pkg.el
+/aidermacs-autoloads.el
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000..4955e59dc5
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,16 @@
+# CHANGELOG
+
+## 1.0 - Initial Release
+
+### Features
+
+-   **Built-in Ediff Integration:** Review AI-generated changes with Emacs' 
familiar `ediff` interface.
+-   **Intelligent Model Selection:** Automatically discover and integrate with 
multiple AI providers (OpenAI, Anthropic, DeepSeek, Google Gemini, OpenRouter).
+-   **Flexible Terminal Backend Support:** Choose between `comint` and `vterm` 
backends for the best terminal compatibility and performance.
+-   **Enhanced File Management:** Easily manage files within your Aider 
session with commands for adding, dropping, listing, and more. Full support for 
remote files via Tramp (SSH, Docker, etc.).
+-   **Streamlined Transient Menu Selection:** Access all Aidermacs features 
through a redesigned and ergonomic transient menu system.
+-   **Prompt Files Minor Mode:** Work seamlessly with prompt files and other 
Aider-related files with convenient keybindings and automatic mode activation.
+-   **Claude 3.7 Sonnet Thinking Tokens:** Enable and configure thinking 
tokens using the `/think-tokens` in-chat command or the `--thinking-tokens` 
command-line argument.
+-   **Architect Mode Confirmation:** Control whether to automatically accept 
Architect mode changes with the `aidermacs-auto-accept-architect` variable.
+-   **Re-Enable Auto-Commits:** Aider automatically commits AI-generated 
changes by default. We consider this behavior *very* intrusive, so we've 
disabled it. You can re-enable auto-commits by setting `aidermacs-auto-commits` 
to `t`.
+-   **Customizing Aider Options with `aidermacs-extra-args`:** Pass any 
Aider-supported command-line options.
diff --git a/README.md b/README.md
index ed82176d0b..3d9c67f1dd 100644
--- a/README.md
+++ b/README.md
@@ -82,6 +82,24 @@ Here's what the community is saying about Aidermacs:
 
 ## Configuration
 
+#### Pre-Run Hook
+
+You can use the `aidermacs-before-run-backend-hook` to run custom setup code 
before starting the Aider backend. This is particularly useful for:
+
+- Setting environment variables
+- Injecting secrets
+- Performing any other pre-run configuration
+
+Example usage to securely set an OpenAI API key from password-store:
+
+```elisp
+(add-hook 'aidermacs-before-run-backend-hook
+          (lambda ()
+            (setenv "OPENAI_API_KEY" (password-store-get 
"code/openai_api_key"))))
+```
+
+This approach keeps sensitive information out of your dotfiles while still 
making it available to Aidermacs.
+
 ### Default Model Selection
 
 You can customize the default AI model used by Aidermacs by setting the 
`aidermacs-default-model` variable:
@@ -133,7 +151,19 @@ When Architect mode is enabled, the 
`aidermacs-default-model` setting is ignored
 (setq aidermacs-editor-model "deepseek/deepseek-chat") ;; defaults to 
aidermacs-default-model
 ```
 
-*Note: This configuration will be overwritten by the existence of an 
`.aider.conf.yml` file (see 
[details](#Overwrite-Configuration-with-Configuration-File)).*
+*Note: These configurations will be overwritten by the existence of an 
`.aider.conf.yml` file (see 
[details](#Overwrite-Configuration-with-Configuration-File)).*
+
+#### Architect Mode Confirmation
+
+By default, Aidermacs requires explicit confirmation before applying changes 
proposed in Architect mode. This gives you a chance to review the AI's plan 
before any code is modified.
+
+If you prefer to automatically accept all Architect mode changes without 
confirmation (similar to Aider's default behavior), you can enable this with:
+
+```emacs-lisp
+(setq aidermacs-auto-accept-architect t)
+```
+
+*Note: These configurations will be overwritten by the existence of an 
`.aider.conf.yml` file (see 
[details](#Overwrite-Configuration-with-Configuration-File)).*
 
 ### Terminal Backend Selection
 
@@ -252,30 +282,19 @@ Aidermacs supports project-specific configurations via 
`.aider.conf.yml` files.
 
 ### Claude 3.7 Sonnet Thinking Tokens
 
-Aider can work with Sonnet 3.7's [new thinking 
tokens](https://www.anthropic.com/news/claude-3-7-sonnet), but does not ask 
Sonnet to use thinking tokens by default.
-
-Enabling thinking currently requires manual configuration. Create an 
`.aider.model.settings.yml` in  your home dir, project's root, or the current 
directory, then add the following to the file. Adjust the `budget_tokens` value 
to change the target number of thinking tokens.
-
-```yaml
-- name: anthropic/claude-3-7-sonnet-20250219
-  edit_format: diff
-  weak_model_name: anthropic/claude-3-5-haiku-20241022
-  use_repo_map: true
-  examples_as_sys_msg: true
-  use_temperature: false
-  extra_params:
-    extra_headers:
-      anthropic-beta: 
prompt-caching-2024-07-31,pdfs-2024-09-25,output-128k-2025-02-19
-    max_tokens: 64000
-    thinking:
-      type: enabled
-      budget_tokens: 32000 # Adjust this number
-  cache_control: true
-  editor_model_name: anthropic/claude-3-7-sonnet-20250219
-  editor_edit_format: editor-diff
-```
+Aider can work with Sonnet 3.7's [new thinking 
tokens](https://www.anthropic.com/news/claude-3-7-sonnet). You can now enable 
and configure thinking tokens more easily using the following methods:
+
+1.  **In-Chat Command:** Use the `/think-tokens` command followed by the 
desired token budget. For example: `/think-tokens 8k` or `/think-tokens 10000`. 
Supported formats include `8096`, `8k`, `10.5k`, and `0.5M`.
+
+2.  **Command-Line Argument:** Set the `--thinking-tokens` argument when 
starting Aidermacs. For example, you can add this to your 
`aidermacs-extra-args`:
+
+    ```emacs-lisp
+    (setq aidermacs-extra-args '("--thinking-tokens" "16k"))
+    ```
+
+These methods provide a more streamlined way to control thinking tokens 
without requiring manual configuration of `.aider.model.settings.yml` files.
 
-More streamlined support will be coming soon.
+*Note: If you are using an `.aider.conf.yml` file, you can also set the 
`thinking_tokens` option there.*
 
 ## Usage
 
diff --git a/aidermacs-backend-comint.el b/aidermacs-backend-comint.el
index 4b73907d4b..d891d04e7f 100644
--- a/aidermacs-backend-comint.el
+++ b/aidermacs-backend-comint.el
@@ -1,6 +1,6 @@
 ;;; aidermacs-backend-comint.el --- Comint backend for aidermacs -*- 
lexical-binding: t; -*-
 ;; Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
-;; Version: 1.0.0
+;; Version: 1.0
 ;; Keywords: ai emacs llm aider ai-pair-programming tools
 ;; URL: https://github.com/MatthewZMD/aidermacs
 ;; SPDX-License-Identifier: Apache-2.0
@@ -31,6 +31,15 @@
 (declare-function aidermacs--show-ediff-for-edited-files "aidermacs")
 (declare-function aidermacs--detect-edited-files "aidermacs")
 (declare-function aidermacs--process-message-if-multi-line "aidermacs" (str))
+(declare-function aidermacs--parse-output-for-files "aidermacs-backends" 
(output))
+(declare-function aidermacs--store-output "aidermacs-backends" (output))
+(declare-function aidermacs--is-aidermacs-buffer-p "aidermacs-backends" 
(&optional buffer))
+
+(defvar aidermacs--last-command)
+
+(defgroup aidermacs-backend-comint nil
+  "Comint backend for Aidermacs."
+  :group 'aidermacs)
 
 (defcustom aidermacs-language-name-map '(("elisp" . "emacs-lisp")
                                          ("bash" . "sh")
@@ -41,6 +50,8 @@
   :type '(alist :key-type (string :tag "Language Name/Alias")
                 :value-type (string :tag "Mode Name (without -mode)")))
 
+;; FIXME: Hmm... seems to use standard diff3 markers.  Maybe some code
+;; in `smerge-mode.el' could be (re)used?
 (defconst aidermacs-search-marker "<<<<<<< SEARCH")
 (defconst aidermacs-diff-marker "=======")
 (defconst aidermacs-replace-marker ">>>>>>> REPLACE")
@@ -63,7 +74,7 @@ This allows for multi-line input without sending the command."
   "Face for commands sent to aidermacs buffer.")
 
 (defface aidermacs-search-replace-block
-  '((t :inherit 'diff-refine-added :bold t))
+  '((t :inherit diff-refine-added :bold t))
   "Face for search/replace block content.")
 
 (defvar aidermacs-font-lock-keywords
diff --git a/aidermacs-backend-vterm.el b/aidermacs-backend-vterm.el
index 24dee78147..d4fbc3af1a 100644
--- a/aidermacs-backend-vterm.el
+++ b/aidermacs-backend-vterm.el
@@ -1,6 +1,6 @@
 ;;; aidermacs-backend-vterm.el --- VTerm backend for aidermacs -*- 
lexical-binding: t; -*-
 ;; Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
-;; Version: 1.0.0
+;; Version: 1.0
 ;; Keywords: ai emacs llm aider ai-pair-programming tools
 ;; URL: https://github.com/MatthewZMD/aidermacs
 ;; SPDX-License-Identifier: Apache-2.0
@@ -47,26 +47,30 @@
 (declare-function aidermacs--is-aidermacs-buffer-p "aidermacs")
 (declare-function aidermacs-get-buffer-name "aidermacs")
 
-;; useful because we want to override "RET" key for evil mode insert state
+(declare-function aidermacs--parse-output-for-files "aidermacs-backends" 
(output))
+
 (declare-function evil-define-minor-mode-key "evil-core")
 
+(defvar aidermacs-prompt-regexp)
+(defvar aidermacs--last-command)
+
+(defgroup aidermacs-backend-vterm nil
+  "VTerm backend for Aidermacs."
+  :group 'aidermacs)
+
 (defvar-local aidermacs--vterm-active-timer nil
   "Store the active timer for vterm output processing.")
 
 (defvar-local aidermacs--vterm-last-check-point nil
   "Store the last position checked in the vterm buffer.")
 
-
 (defvar-local aidermacs-vterm-check-interval 0.7
   "Interval in seconds between checks for command completion in vterm.")
 
-
 (defcustom aidermacs-vterm-multiline-newline-key "S-<return>"
   "Key binding to enter a newline without sending in vterm."
   :type 'string)
 
-(defvar aidermacs-prompt-regexp)
-
 (defun aidermacs--vterm-check-finish-sequence-repeated (proc orig-filter 
start-point)
   "Check for the finish sequence in PROC's buffer.
 PROC is the process to check.  ORIG-FILTER is the original process filter.
@@ -145,7 +149,7 @@ after each output chunk, reducing the need for timers."
 (defun aidermacs--maybe-cancel-active-timer (&optional buffer)
   "Cancel the active timer if it exists.
 Use BUFFER if provided, otherwise retrieve it from 
`aidermacs-get-buffer-name'."
-  (when-let ((buf (get-buffer (or buffer (aidermacs-get-buffer-name)))))
+  (when-let* ((buf (get-buffer (or buffer (aidermacs-get-buffer-name)))))
     (with-current-buffer buf
       (when (timerp aidermacs--vterm-active-timer)
         (cancel-timer aidermacs--vterm-active-timer)
diff --git a/aidermacs-backends.el b/aidermacs-backends.el
index 2556c6e256..9f37f4da0d 100644
--- a/aidermacs-backends.el
+++ b/aidermacs-backends.el
@@ -1,6 +1,6 @@
 ;;; aidermacs-backends.el --- Backend dispatcher for aidermacs -*- 
lexical-binding: t; -*-
 ;; Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
-;; Version: 1.0.0
+;; Version: 1.0
 ;; Keywords: ai emacs llm aider ai-pair-programming tools
 ;; URL: https://github.com/MatthewZMD/aidermacs
 ;; SPDX-License-Identifier: Apache-2.0
@@ -32,6 +32,10 @@
 (declare-function aidermacs--prepare-for-code-edit "aidermacs" ())
 (declare-function aidermacs--get-files-in-session "aidermacs" (callback))
 
+(defgroup aidermacs-backends nil
+  "Backend dispatcher for aidermacs."
+  :group 'aidermacs)
+
 (defcustom aidermacs-backend 'comint
   "Backend to use for the aidermacs process.
 Options are `comint' (the default) or `vterm'.  When set to `vterm',
@@ -54,6 +58,10 @@ Each entry is a cons cell (timestamp . output-text).")
 (defvar-local aidermacs--current-output ""
   "Accumulator for current output being captured as a string.")
 
+(defcustom aidermacs-before-run-backend-hook nil
+  "Hook run before the aidermacs backend is startd."
+  :type 'hook)
+
 (defun aidermacs-get-output-history (&optional limit)
   "Get the output history, optionally limited to LIMIT entries.
 LIMIT is the maximum number of entries to return.
@@ -81,91 +89,81 @@ This is used to avoid having to run /ls repeatedly.")
 (defun aidermacs--parse-output-for-files (output)
   "Parse OUTPUT for files and add them to `aidermacs--tracked-files'."
   (when output
-    (let ((tracked-files aidermacs--tracked-files))
-      (with-temp-buffer
-        (insert output)
-        (goto-char (point-min))
-
-        ;; Applied edit to <filename>
-        (while (search-forward "Applied edit to" nil t)
-          (beginning-of-line)
-          (when-let ((file (and (looking-at ".*Applied edit to 
\\(\\./\\)?\\(.+\\)")
-                                (match-string-no-properties 2))))
-            (add-to-list 'tracked-files file))
-          (forward-line 1))
-
-        ;; Combined file tracking logic
-        (goto-char (point-min))
-        (while (re-search-forward
-                "\\(Added\\|Removed\\|Moved\\) \\(\\./\\)?\\([^ ]+\\) 
\\(to\\|from\\) \\(the chat\\|editable\\|read-only\\) files?"
-                nil t)
-          (let* ((action (match-string 1))
-                 (file (match-string 3))
-                 (state (match-string 5)))
-            (cond
-             ;; Added files
-             ((string= action "Added")
-              (add-to-list 'tracked-files
-                           (if (string= state "read-only")
-                               (concat file " (read-only)")
-                             file)))
-
-             ;; Removed files
-             ((string= action "Removed")
-              (setq tracked-files (delete file tracked-files)))
-
-             ;; Moved files
-             ((string= action "Moved")
-              (let* ((from-state (if (string= state "editable") "read-only" 
"editable"))
-                     (old-file (if (string= from-state "read-only")
-                                   (concat file " (read-only)")
-                                 file))
-                     (new-file (if (string= state "read-only")
-                                   (concat file " (read-only)")
-                                 file)))
-                (setq tracked-files (delete old-file tracked-files))
-                (add-to-list 'tracked-files new-file))))))
-
-        ;; <file> is already in the chat as an editable file
-        (goto-char (point-min))
-        (while (search-forward " is already in the chat as an editable file" 
nil t)
-          (beginning-of-line)
-          (when-let ((file (and (looking-at "\\(\\./\\)?\\(.+\\) is already in 
the chat as an editable file")
-                                (match-string-no-properties 2))))
-            (add-to-list 'tracked-files file))
-          (forward-line 1))
-
-        ;; Add file to the chat?
-        (goto-char (point-min))
-        (while (search-forward "Add file to the chat?" nil t)
-          (save-excursion
-            (forward-line -1)
-            (let ((potential-file (string-trim (buffer-substring 
(line-beginning-position) (line-end-position)))))
-              (when (not (string-empty-p potential-file))
-                (add-to-list 'tracked-files potential-file)
-                (aidermacs--prepare-for-code-edit))))
-          (forward-line 1))
-
-        ;; Handle udiff format
-        (goto-char (point-min))
-        (while (search-forward "--- " nil t)
-          (message "processing %s " tracked-files)
-          (let* ((line-end (line-end-position))
-                 (current-udiff-file (when (looking-at "\\(\\./\\)?\\(.+\\)")
-                                       (match-string-no-properties 2))))
-            (when current-udiff-file
-              (forward-line 1)
-              (when (looking-at "\\+\\+\\+ \\(\\./\\)?\\(.+\\)")
-                (let ((plus-file (match-string-no-properties 2)))
-                  (when (string= (file-name-nondirectory current-udiff-file)
-                                 (file-name-nondirectory plus-file))
-                    (add-to-list 'tracked-files current-udiff-file))))))))
+    (let ((lines (split-string output "\n"))
+          (last-line "")
+          (in-udiff nil)
+          (current-udiff-file nil))
+      (dolist (line lines)
+        (cond
+         ;; Applied edit to <filename>
+         ((string-match "Applied edit to \\(\\./\\)?\\(.+\\)" line)
+          (when-let ((file (match-string 2 line)))
+            (add-to-list 'aidermacs--tracked-files file)))
+
+         ;; Added <filename> to the chat.
+         ((string-match "Added \\(\\./\\)?\\(.+\\) to the chat" line)
+          (when-let ((file (match-string 2 line)))
+            (add-to-list 'aidermacs--tracked-files file)))
+
+         ;; Removed <filename> from the chat (with or without ./ prefix)
+         ((string-match "Removed \\(\\./\\)?\\(.+\\) from the chat" line)
+          (when-let ((file (match-string 2 line)))
+            (setq aidermacs--tracked-files (delete file 
aidermacs--tracked-files))))
+
+         ;; Added <filename> to read-only files.
+         ((string-match "Added \\(\\./\\)?\\(.+\\) to read-only files" line)
+          (when-let ((file (match-string 2 line)))
+            (add-to-list 'aidermacs--tracked-files (concat file " 
(read-only)"))))
+
+         ;; Moved <file> from editable to read-only files in the chat
+         ((string-match "Moved \\(\\./\\)?\\(.+\\) from editable to read-only 
files in the chat" line)
+          (when-let ((file (match-string 2 line)))
+            (let ((editable-file (replace-regexp-in-string " (read-only)$" "" 
file)))
+              (setq aidermacs--tracked-files (delete editable-file 
aidermacs--tracked-files))
+              (add-to-list 'aidermacs--tracked-files (concat file " 
(read-only)")))))
+
+         ;; Moved <file> from read-only to editable files in the chat
+         ((string-match "Moved \\(\\./\\)?\\(.+\\) from read-only to editable 
files in the chat" line)
+          (when-let ((file (match-string 2 line)))
+            (let ((read-only-file (concat file " (read-only)")))
+              (setq aidermacs--tracked-files (delete read-only-file 
aidermacs--tracked-files))
+              (add-to-list 'aidermacs--tracked-files file))))
+
+         ;; <file>\nAdd file to the chat?
+         ((string-match "Add file to the chat?" line)
+          (add-to-list 'aidermacs--tracked-files last-line)
+          (aidermacs--prepare-for-code-edit))
+
+         ;; <file> is already in the chat as an editable file
+         ((string-match "\\(\\./\\)?\\(.+\\) is already in the chat as an 
editable file" line)
+          (when-let ((file (match-string 2 line)))
+            (add-to-list 'aidermacs--tracked-files file)))
+
+         ;; Handle udiff format
+         ;; Detect start of udiff with "--- filename"
+         ((string-match "^--- \\(\\./\\)?\\(.+\\)" line)
+          (setq in-udiff t
+                current-udiff-file (match-string 2 line)))
+
+         ;; Confirm udiff file with "+++ filename" line
+         ((and in-udiff
+               current-udiff-file
+               (string-match "^\\+\\+\\+ \\(\\./\\)?\\(.+\\)" line))
+          (let ((plus-file (match-string 2 line)))
+            ;; Only add if the filenames match (ignoring ./ prefix)
+            (when (string= (file-name-nondirectory current-udiff-file)
+                           (file-name-nondirectory plus-file))
+              (add-to-list 'aidermacs--tracked-files current-udiff-file)
+              (setq in-udiff nil
+                    current-udiff-file nil)))))
+
+        (setq last-line line))
 
       ;; Verify all tracked files exist
       (let* ((project-root (aidermacs-project-root))
              (is-remote (file-remote-p project-root))
              (valid-files nil))
-        (dolist (file tracked-files)
+        (dolist (file aidermacs--tracked-files)
           (let* ((is-readonly (string-match-p " (read-only)$" file))
                  (actual-file (if is-readonly
                                   (substring file 0 (- (length file) 12))
@@ -173,15 +171,7 @@ This is used to avoid having to run /ls repeatedly.")
                  (full-path (expand-file-name actual-file project-root)))
             (when (or (file-exists-p full-path) is-remote)
               (push file valid-files))))
-        (setq tracked-files valid-files))
-      (setq aidermacs--tracked-files tracked-files))))
-
-(defun aidermacs-reset-tracked-files ()
-  "Reset the list of tracked files and force a refresh."
-  (interactive)
-  (setq aidermacs--tracked-files nil)
-  (aidermacs--get-files-in-session (lambda (files)
-                                     (message "Refreshed file list: %s" 
files))))
+        (setq aidermacs--tracked-files valid-files)))))
 
 (defun aidermacs--store-output (output)
   "Store output string in the history with timestamp.
@@ -210,6 +200,7 @@ If there's a callback function, call it with the output."
 PROGRAM is the aidermacs executable path.  ARGS are command line arguments.
 BUFFER-NAME is the name for the aidermacs buffer."
   (message "Running %s with %s" program args)
+  (run-hooks 'aidermacs-before-run-backend-hook)
   (cond
    ((eq aidermacs-backend 'vterm)
     (aidermacs-run-vterm program args buffer-name))
diff --git a/aidermacs-models.el b/aidermacs-models.el
index 0fdcdafa9e..60f4db8305 100644
--- a/aidermacs-models.el
+++ b/aidermacs-models.el
@@ -1,6 +1,6 @@
 ;;; aidermacs-models.el --- Model selection for aidermacs -*- lexical-binding: 
t; -*-
 ;; Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
-;; Version: 1.0.0
+;; Version: 1.0
 ;; Keywords: ai emacs llm aider ai-pair-programming tools
 ;; URL: https://github.com/MatthewZMD/aidermacs
 ;; SPDX-License-Identifier: Apache-2.0
@@ -32,6 +32,10 @@
 (declare-function aidermacs-buffer-name "aidermacs" ())
 (declare-function aidermacs-exit "aidermacs" ())
 
+(defgroup aidermacs-models nil
+  "Model selection for Aidermacs."
+  :group 'aidermacs)
+
 (defcustom aidermacs-default-model "sonnet"
   "Default AI model to use for aidermacs sessions when not in Architect mode."
   :type 'string)
diff --git a/aidermacs.el b/aidermacs.el
index 238bd39478..cbcd75dffd 100644
--- a/aidermacs.el
+++ b/aidermacs.el
@@ -1,6 +1,6 @@
 ;;; aidermacs.el --- AI pair programming with Aider -*- lexical-binding: t; -*-
 ;; Author: Mingde (Matthew) Zeng <matthew...@posteo.net>
-;; Version: 1.0.0
+;; Version: 1.0
 ;; Package-Requires: ((emacs "29.1"))
 ;; Keywords: ai emacs llm aider ai-pair-programming tools
 ;; URL: https://github.com/MatthewZMD/aidermacs
@@ -35,10 +35,15 @@
 (require 'ansi-color)
 (require 'cl-lib)
 (require 'tramp)
+(require 'find-dired)
 
 (require 'aidermacs-backends)
 (require 'aidermacs-models)
 
+(defgroup aidermacs nil
+  "AI pair programming with Aider."
+  :group 'aidermacs)
+
 (defvar-local aidermacs--current-mode nil
   "Buffer-local variable to track the current aidermacs mode.
 Possible values: `code', `ask', `architect', `help'.")
@@ -78,10 +83,15 @@ This is useful for working in monorepos where you want to 
limit aider's scope."
 When nil, disable auto-commits requiring manual git commits."
   :type 'boolean)
 
+(defcustom aidermacs-auto-accept-architect nil
+  "When non-nil, automatically accept architect mode changes.
+When nil, require explicit confirmation before applying changes."
+  :type 'boolean)
+
 (defun aidermacs-project-root ()
   "Get the project root using project.el, VC, or fallback to file directory.
 This function tries multiple methods to determine the project root."
-  (or (when-let ((proj (project-current)))
+  (or (when-let* ((proj (project-current)))
         (project-root proj))
       (vc-git-root default-directory)
       (when buffer-file-name
@@ -255,8 +265,10 @@ This function sets up the appropriate arguments and 
launches the process."
                        "--editor-model" aidermacs-editor-model)
                (unless has-model-arg
                  (list "--model" aidermacs-default-model)))
-             (when (not aidermacs-auto-commits)
+             (unless aidermacs-auto-commits
                '("--no-auto-commits"))
+             (unless aidermacs-auto-accept-architect
+               '("--no-auto-accept-architect"))
              (when aidermacs-subtree-only
                '("--subtree-only")))))
          (final-args (append backend-args flat-extra-args)))
@@ -376,7 +388,7 @@ Returns a list of files that have been modified according 
to the output."
         ;; Case 1: Find "Applied edit to" lines
         (while (search-forward "Applied edit to" nil t)
           (beginning-of-line)
-          (when-let ((file (and (looking-at ".*Applied edit to 
\\(\\./\\)?\\([^[:space:]]+\\)")
+          (when-let* ((file (and (looking-at ".*Applied edit to 
\\(\\./\\)?\\([^[:space:]]+\\)")
                                 (match-string-no-properties 2))))
             (push file edited-files))
           (forward-line 1))
@@ -514,7 +526,7 @@ If the current buffer is already the aidermacs buffer, do 
nothing."
      (buffer
       (pop-to-buffer buffer))
      (t
-      (error "No aidermacs buffer exists.")))))
+      (error "No aidermacs buffer exists")))))
 
 (defun aidermacs-clear-chat-history ()
   "Send the command \"/clear\" to the aidermacs buffer."
@@ -643,7 +655,8 @@ Sends the \"/ls\" command and displays the results in a 
Dired buffer."
                      ;; The executed command is on the 2nd line; it can get
                      ;; quite long, so we delete it to avoid cluttering the
                      ;; buffer.
-                     (goto-line 2)
+                     (goto-char (point-min))
+                     (forward-line 1)  ;; Move to the 2nd line
                      (when (looking-at "^ *find " t)
                        (let ((inhibit-read-only t))
                          (delete-region (line-beginning-position) 
(line-end-position)))))
@@ -665,6 +678,7 @@ Sends the \"/ls\" command and displays the results in a 
Dired buffer."
 (defun aidermacs-drop-all-files ()
   "Drop all files from the current chat session."
   (interactive)
+  (setq aidermacs--tracked-files nil)
   (aidermacs--send-command "/drop"))
 
 (defun aidermacs-batch-drop-dired-marked-files ()
@@ -719,7 +733,7 @@ Use highlighted region as context unless IGNORE-CONTEXT is 
set to non-nil."
   (let* ((region-text (when (and (use-region-p) (not ignore-context))
                         (buffer-substring-no-properties (region-beginning) 
(region-end))))
          (context (when region-text
-                    (format " regarding this section:\n```\n%s\n```\n" 
region-text)))
+                    (format " in %s regarding this section:\n```\n%s\n```\n" 
(buffer-name) region-text)))
          (user-command (read-string (concat command " " prompt-prefix context
                                             (when guide (format " (%s)" 
guide)) ": "))))
     (concat command (and (not (string-empty-p user-command))
@@ -728,7 +742,7 @@ Use highlighted region as context unless IGNORE-CONTEXT is 
set to non-nil."
 (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" "Make this change" "will 
edit file")))
+  (when-let* ((command (aidermacs--form-prompt "/code" "Make this change" 
"will edit file")))
     (aidermacs--ensure-current-file-tracked)
     (aidermacs--send-command command)))
 
@@ -738,7 +752,7 @@ If a region is active, include the region text in the 
question.
 If cursor is inside a function, include the function name as context.
 If called from the aidermacs buffer, use general question instead."
   (interactive)
-  (when-let ((command (aidermacs--form-prompt "/ask" "Propose a solution" 
"won't edit file")))
+  (when-let* ((command (aidermacs--form-prompt "/ask" "Propose a solution" 
"won't edit file")))
     (aidermacs--ensure-current-file-tracked)
     (aidermacs--send-command command)))
 
@@ -747,26 +761,26 @@ If called from the aidermacs buffer, use general question 
instead."
 If region is active, inspect that region.
 If point is in a function, inspect that function."
   (interactive)
-  (when-let ((command (aidermacs--form-prompt "/architect" "Design a solution" 
"confirm before edit")))
+  (when-let* ((command (aidermacs--form-prompt "/architect" "Design a 
solution" "confirm before edit")))
     (aidermacs--ensure-current-file-tracked)
     (aidermacs--send-command command)))
 
 (defun aidermacs-question-general ()
   "Prompt the user for a general question without code context."
   (interactive)
-  (when-let ((command (aidermacs--form-prompt "/ask" nil "empty for ask mode" 
t)))
+  (when-let* ((command (aidermacs--form-prompt "/ask" nil "empty for ask mode" 
t)))
     (aidermacs--send-command command)))
 
 (defun aidermacs-help ()
   "Prompt the user for an input prefixed with \"/help \"."
   (interactive)
-  (when-let ((command (aidermacs--form-prompt "/help" nil "question how to use 
aider, empty for all commands" t)))
+  (when-let* ((command (aidermacs--form-prompt "/help" nil "question how to 
use aider, empty for all commands" t)))
     (aidermacs--send-command command)))
 
 (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")))
+  (when-let* ((command (aidermacs--form-prompt "/ask" "Debug exception")))
     (aidermacs--send-command command)))
 
 (defun aidermacs-accept-change ()
@@ -939,7 +953,7 @@ Otherwise:
   - Otherwise generate unit tests for the entire file"
   (interactive)
   (if (not buffer-file-name)
-      (user-error "Current buffer is not visiting a file.")
+      (user-error "Current buffer is not visiting a file")
     (let ((function-name (which-function)))
       (cond
        ;; Test file case
@@ -972,7 +986,7 @@ Otherwise:
   "Report the current test failure to aidermacs and ask it to fix the code.
 This function assumes the cursor is on or inside a test function."
   (interactive)
-  (if-let ((test-function-name (which-function)))
+  (if-let* ((test-function-name (which-function)))
       (let* ((initial-input (format "The test '%s' is failing. Please analyze 
and fix the code to make the test pass. Don't break any other test"
                                     test-function-name))
              (command (aidermacs--form-prompt "/architect" initial-input)))
@@ -1002,7 +1016,7 @@ snippets, or other content to the session."
     (message "Created and added scratchpad to session: %s" filename)))
 
 (defun aidermacs-add-file-to-session (&optional file)
-  "Interactively add a file to an existing aidermacs session using /read.
+  "Interactively add a FILE to an existing aidermacs session using /read.
 This allows you to add the file's content to a specific session."
   (interactive
    (let* ((initial (when buffer-file-name
@@ -1046,7 +1060,7 @@ Otherwise implement TODOs for the entire current file."
       (message "Current buffer is not visiting a file.")
     (let* ((current-line (string-trim (thing-at-point 'line t)))
            (is-comment (aidermacs--is-comment-line current-line)))
-      (when-let ((command (aidermacs--form-prompt
+      (when-let* ((command (aidermacs--form-prompt
                            "/architect"
                            (concat "Please implement the TODO items."
                                    (and is-comment
@@ -1119,10 +1133,10 @@ sample prompt."
 ;;;###autoload
 (defvar aidermacs-minor-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map (kbd "C-c C-n") 'aidermacs-send-line-or-region)
-    (define-key map (kbd "C-<return>") 'aidermacs-send-line-or-region)
-    (define-key map (kbd "C-c C-c") 'aidermacs-send-block-or-region)
-    (define-key map (kbd "C-c C-z") 'aidermacs-switch-to-buffer)
+    (define-key map (kbd "C-c C-n") #'aidermacs-send-line-or-region)
+    (define-key map (kbd "C-<return>") #'aidermacs-send-line-or-region)
+    (define-key map (kbd "C-c C-c") #'aidermacs-send-block-or-region)
+    (define-key map (kbd "C-c C-z") #'aidermacs-switch-to-buffer)
     map)
   "Keymap for `aidermacs-minor-mode'.")
 

Reply via email to