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

    Rewrite aidermacs--pick-project-file
---
 aidermacs.el | 153 ++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 100 insertions(+), 53 deletions(-)

diff --git a/aidermacs.el b/aidermacs.el
index 65ec39f801..5f4d8ce0e9 100644
--- a/aidermacs.el
+++ b/aidermacs.el
@@ -243,44 +243,54 @@ If supplied, SUFFIX is appended to the buffer name within 
the earmuffs."
   (if use-existing
       (aidermacs-select-buffer-name)
     (let* ((root (aidermacs-project-root))
-           ;; Get all existing aidermacs buffers
-           (aidermacs-buffers
-            (match-buffers #'aidermacs--is-aidermacs-buffer-p))
-           ;; Extract directory paths and subtree status from buffer names
-           (buffer-dirs
-            (mapcar
-             (lambda (buf)
-               (when (string-match "^\\*aidermacs:\\(.*?\\)\\*$"
-                                   (buffer-name buf))
-                 (cons (match-string 1 (buffer-name buf))
-                       (match-string 2 (buffer-name buf)))))
-             aidermacs-buffers))
-           ;; Find closest parent directory that has an aidermacs session
-           (closest-parent
-            (caar
-             (sort
-              (cl-remove-if-not
-               (lambda (dir-info)
-                 (and (car dir-info)
-                      (file-in-directory-p default-directory (car dir-info))
-                      (file-exists-p (car dir-info))))
-               buffer-dirs)
-              (lambda (a b)
-                ;; Sort by length of filenames (deeper filenames first)
-                (> (length (car a)) (length (car b)))))))
-           (display-root (cond
-                          ;; Use current directory for new subtree session
-                          (aidermacs-subtree-only default-directory)
-                          ;; Use closest parent if it exists
-                          (closest-parent
-                           (if (<= (length (expand-file-name closest-parent))
-                                   (length (expand-file-name root)))
-                               root
-                             closest-parent))
-                          ;; Fall back to project root for new non-subtree 
session
-                          (t root))))
+           (current-dir-truename (file-truename default-directory)) ; Use 
truename for consistent comparisons
+           (aidermacs-buffers (match-buffers 
#'aidermacs--is-aidermacs-buffer-p))
+           ;; Extract truename paths from existing *aidermacs:PATH* buffers 
(base sessions)
+           (existing-session-paths
+            (delq nil
+                  (mapcar (lambda (buf)
+                            (when (string-match 
"^\\*aidermacs:\\([^\\*]+\\)\\*$" (buffer-name buf)) ; Match base session names
+                              (let ((path-str (match-string 1 (buffer-name 
buf))))
+                                (when (file-directory-p path-str) ; Ensure 
it's a directory
+                                  (file-truename path-str)))))
+                          aidermacs-buffers)))
+
+           ;; Determine the display-root for the buffer name
+           (display-root
+            (let* ((sessions-containing-current-dir ;; Sessions whose paths 
contain current-dir-truename
+                    (sort (cl-remove-if-not
+                           (lambda (session-path)
+                             (file-in-directory-p current-dir-truename 
session-path))
+                           existing-session-paths)
+                          ;; Sort by length (deeper paths are more specific)
+                          (lambda (a b) (> (length a) (length b)))))
+                   (closest-session-containing-current-dir (car 
sessions-containing-current-dir))
+
+                   (sessions-within-current-dir ;; Sessions whose paths are 
within current-dir-truename
+                    (sort (cl-remove-if-not
+                           (lambda (session-path)
+                             (file-in-directory-p session-path 
current-dir-truename))
+                           existing-session-paths)
+                          ;; Sort by length (deeper paths are more specific)
+                          (lambda (a b) (> (length a) (length b))))))
+
+              (cond
+               ;; 1. Current directory is INSIDE an existing session's 
directory.
+               (closest-session-containing-current-dir
+                closest-session-containing-current-dir)
+
+               ;; 2. Current directory is an ANCESTOR of exactly ONE existing 
session.
+               ((and (not closest-session-containing-current-dir) ; Only if 
not already covered by case 1
+                     sessions-within-current-dir
+                     (= 1 (length sessions-within-current-dir)))
+                (car sessions-within-current-dir))
+
+               ;; 3. Fallback logic (original logic for new session or 
ambiguous cases).
+               (aidermacs-subtree-only current-dir-truename)
+               (t (file-truename root)))))) ; Ensure root is also truename for 
consistency
+
       (format "*aidermacs:%s%s*"
-              (file-truename display-root)
+              display-root
               (or suffix "")))))
 
 (defun aidermacs--live-p (buffer-name)
@@ -790,23 +800,60 @@ With prefix argument `C-u', add as read-only."
              (if read-only "read-only" "editable")))))
 
 (defun aidermacs--pick-project-file ()
-  "Prompt for a file in the current project using `completing-read`."
-  (let* ((curr-project-root (or (aidermacs-project-root) (user-error "No 
project root found")))
-         (files
+  "Prompt for a file in the current project using `completing-read`.
+This function attempts to use `project.el` to find files if available
+and consistent with `aidermacs-project-root`. Otherwise, it falls back
+to a recursive directory listing based on `aidermacs-project-root`."
+  (interactive)
+  (let* ((aidermacs-root-raw (aidermacs-project-root))
+         (aidermacs-root (when aidermacs-root-raw (expand-file-name 
aidermacs-root-raw)))
+         (project-files-list nil)
+         (base-for-relativization aidermacs-root))
+
+    (unless aidermacs-root
+      (user-error "No project root found by aidermacs-project-root"))
+
+    (if (and (fboundp 'project-files) (project-current))
+        (let* ((proj (project-current)) ; proj is (TYPE . DIR) or (TYPE . (Git 
"DIR"))
+               (project-el-root-candidate (cdr proj)) ; This can be DIR string 
or a list like (Git "DIR")
+               (project-el-root-str
+                (cond
+                 ((stringp project-el-root-candidate) 
project-el-root-candidate)
+                 ;; Handles (SYMBOL "path" ...) e.g. (Git "/path/to/root")
+                 ((and (consp project-el-root-candidate)
+                       (symbolp (car project-el-root-candidate))
+                       (>= (length project-el-root-candidate) 2)
+                       (stringp (nth 1 project-el-root-candidate)))
+                  (nth 1 project-el-root-candidate))
+                 (t nil)))
+               (project-el-root-expanded (when project-el-root-str 
(expand-file-name project-el-root-str))))
+
           (cond
-           ((and curr-project-root
-                 ;; `project-files' can only be used in in Emacs 27.1+
-                 (fboundp 'project-files))
-            ;; Ensure that `project-current' is the same as aidermacs
-            (unless (string= (expand-file-name curr-project-root) 
(expand-file-name (cdr (project-current))))
-              (user-error "(project-current) does not match 
(aidermacs-project-root)"))
-            (project-files (project-current)))
-           ;; Fallback to recursive directory listing
-           (t (directory-files-recursively curr-project-root ".*" t))))
-         (choices (mapcar (lambda (f) (file-relative-name f 
curr-project-root)) files))
-         (file (completing-read "Select project file to add: " choices))
-         (absolute-file (expand-file-name file curr-project-root)))
-    absolute-file))
+           ((not project-el-root-expanded)
+            (message "aidermacs--pick-project-file: Could not determine 
project.el root string. Falling back to recursive listing based on 
aidermacs-project-root."))
+           ((string= aidermacs-root project-el-root-expanded)
+            (setq project-files-list (project-files proj))
+            (setq base-for-relativization project-el-root-expanded)
+            (unless project-files-list
+              (message "aidermacs--pick-project-file: project-files for '%s' 
returned no files. Falling back." project-el-root-expanded)))
+           (t
+            (message "aidermacs--pick-project-file: aidermacs-project-root 
(%s) differs from project.el root (%s). Falling back to recursive listing based 
on aidermacs-project-root."
+                     aidermacs-root project-el-root-expanded))))
+      (message "aidermacs--pick-project-file: project.el not available or no 
current project. Falling back to recursive listing based on 
aidermacs-project-root."))
+
+    ;; Fallback if project-files were not used or yielded no files
+    (unless project-files-list
+      (setq project-files-list (directory-files-recursively aidermacs-root 
".*" t))
+      (setq base-for-relativization aidermacs-root)) ; Ensure base is set for 
fallback
+
+    (unless project-files-list
+      (user-error "No files found in project: %s" base-for-relativization))
+
+    (let* ((choices (mapcar (lambda (f) (file-relative-name f 
base-for-relativization))
+                            project-files-list))
+           (selected-relative-file (completing-read "Select project file to 
add: " choices nil t)))
+      (when selected-relative-file
+        (expand-file-name selected-relative-file base-for-relativization)))))
 
 (defun aidermacs-add-file (&optional read-only)
   "Add file(s) to aidermacs interactively.

Reply via email to