Subject: bug#62621: 29.0.60; uniquify can't make buffers unique based on things other than filename

From: Spencer Baugh <[email-masked]>
Date: Fri, 14 Apr 2023 12:08:37 -0400

FWIW, here is the (unpolished) patch I'm currently using.

This is correct but it's not what I think the final form of this should
look like.

For better or for worse, I have now Deeply Understood uniquify, and I
have various ideas for things to do to fix bugs in it and simplify it
and add new features... see bug#62732 for my first step.  (Which adds
tests, even!)

After some of those, then I can do this bug.

One sneak peak of a feature which I think I can manage to add with some
improvements to uniquify.el: a user customization which causes a new
behavior in read-buffer, so that when it's running on a subset of
buffers (by passing PREDICATE), it reads buffer names which are only
uniquified among that subset.  (So the buffer names will be shorter when
that doesn't cause ambiguity).  This would be really cool for
project-switch-to-buffer, so that if you have two projects working on
the same source repo with the same files open, you don't have to see the
extra uniquify cruft at the start of the buffer name when you just want
to look at buffers in a single project.

diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index dee9ecba2ea..53b39920820 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -210,8 +210,8 @@ uniquify-rationalize-file-buffer-names
   (with-current-buffer newbuf (setq uniquify-managed nil))
   (when dirname
     (setq dirname (expand-file-name (directory-file-name dirname)))
-    (let ((fix-list (list (uniquify-make-item base dirname newbuf
-                                              nil dirname)))
+    (let ((fix-list (list (let ((dirname (uniquify-buffer-file-name newbuf dirname)))
+                            (uniquify-make-item base dirname newbuf nil dirname))))
 	  items)
       (dolist (buffer (buffer-list))
 	(when (and (not (and uniquify-ignore-buffers-re
@@ -258,20 +258,26 @@ uniquify-rationalize-file-buffer-names
       (uniquify-rationalize fix-list))))
 
 ;; uniquify's version of buffer-file-name; result never contains trailing slash
-(defun uniquify-buffer-file-name (buffer)
+(require 'project)
+(defun uniquify-buffer-file-name (buffer &optional dirname)
   "Return name of directory, file BUFFER is visiting, or nil if none.
 Works on ordinary file-visiting buffers and buffers whose mode is mentioned
 in `uniquify-list-buffers-directory-modes', otherwise returns nil."
   (with-current-buffer buffer
-    (let ((filename
-	   (or buffer-file-name
-	       (if (memq major-mode uniquify-list-buffers-directory-modes)
-		   list-buffers-directory))))
-      (when filename
-	(directory-file-name
-	 (file-name-directory
-	  (expand-file-name
-	   (directory-file-name filename))))))))
+    (let* ((filename
+	    (or buffer-file-name
+	        (if (memq major-mode uniquify-list-buffers-directory-modes)
+		    list-buffers-directory)))
+           (dir (or dirname
+                    (directory-file-name
+	             (file-name-directory
+	              (expand-file-name
+	               (directory-file-name filename)))))))
+      (if-let (pr (project-current nil dir))
+          (let* ((pr-dir (project-root pr))
+                 (pr-rel (file-relative-name dir pr-dir)))
+            (file-name-concat pr-dir (project-name pr) pr-rel))
+        dir))))
 
 (defun uniquify-rerationalize-w/o-cb (fix-list)
   "Re-rationalize the buffers in FIX-LIST, but ignoring `current-buffer'."