aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSpencer Baugh2023-07-09 22:21:03 -0400
committerEli Zaretskii2023-07-26 17:41:48 +0300
commit2aec67f4deb1a7dfd87f7da8479be4b2784bcc39 (patch)
tree30f1ffd66cc9385a42d7c34bf4f0bbe4dd269347
parent4ef9cc5a5ded7156e573a67474f3f48da6c7afe4 (diff)
downloademacs-2aec67f4deb1a7dfd87f7da8479be4b2784bcc39.tar.gz
emacs-2aec67f4deb1a7dfd87f7da8479be4b2784bcc39.zip
Support transforming the dirname used by uniquify
By transforming the buffer's directory name, we can add additional information to use during uniquifying. A basic one: uniquifying buffer names based on the project name. * lisp/progmodes/project.el (project-uniquify-dirname-transform): Add. * lisp/uniquify.el (uniquify-dirname-transform-default) (uniquify-dirname-transform): Add. (Bug#62621) (uniquify-rationalize-file-buffer-names, uniquify-buffer-file-name): Use 'uniquify-dirname-transform'. * test/lisp/uniquify-tests.el (uniquify-home) (uniquify-project-transform): Add tests.
-rw-r--r--lisp/progmodes/project.el17
-rw-r--r--lisp/uniquify.el37
-rw-r--r--test/lisp/uniquify-tests.el33
3 files changed, 82 insertions, 5 deletions
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 03ed966cc45..e7deee43f8e 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1887,5 +1887,22 @@ to directory DIR."
1887 (let ((project-current-directory-override dir)) 1887 (let ((project-current-directory-override dir))
1888 (call-interactively command)))) 1888 (call-interactively command))))
1889 1889
1890;;;###autoload
1891(defun project-uniquify-dirname-transform (dirname)
1892 "Include `project-name' in DIRNAME if in a project.
1893
1894If you set `uniquify-dirname-transform' to this function,
1895slash-separated components from `project-name' will be added to
1896the buffer's name when buffers from two different projects would
1897otherwise have the same name."
1898 (if-let (proj (project-current nil dirname))
1899 (let ((root (project-root proj)))
1900 (expand-file-name
1901 (file-name-concat
1902 (file-name-directory root)
1903 (project-name proj)
1904 (file-relative-name dirname root))))
1905 dirname))
1906
1890(provide 'project) 1907(provide 'project)
1891;;; project.el ends here 1908;;; project.el ends here
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index d1ca455b673..af00c95663d 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -168,6 +168,31 @@ This can be handy when you have deep parallel hierarchies."
168That means that when `buffer-file-name' is set to nil, `list-buffers-directory' 168That means that when `buffer-file-name' is set to nil, `list-buffers-directory'
169contains the name of the directory which the buffer is visiting.") 169contains the name of the directory which the buffer is visiting.")
170 170
171(defcustom uniquify-dirname-transform #'identity
172 "Function to transform buffer's directory for uniquifying its name.
173
174If `uniquify-buffer-name-style' is non-nil and a buffer's name
175would be the same as some other buffer, then components from the
176buffer's directory name are added to the buffer's name until the
177buffer's name is unique.
178
179This function is used to transform the buffer's directory name
180before the uniquifying process, allowing the unique buffer name
181to include components from other sources. The default is
182`identity', so only the buffer's directory name is used for
183uniquifying. This function is called with the buffer's directory
184name and should return a file name (which does not need to
185actually exist in the filesystem) to use components from.
186
187To include components from `project-name', set this variable to
188`project-uniquify-dirname-transform'."
189 :type '(choice (function-item :tag "Don't change the dirname" identity)
190 (function-item :tag "Include project name in dirname"
191 #'project-uniquify-dirname-transform)
192 function)
193 :version "30.1"
194 :group 'uniquify)
195
171;;; Utilities 196;;; Utilities
172 197
173;; uniquify-fix-list data structure 198;; uniquify-fix-list data structure
@@ -209,7 +234,8 @@ this rationalization."
209 ;; this buffer. 234 ;; this buffer.
210 (with-current-buffer newbuf (setq uniquify-managed nil)) 235 (with-current-buffer newbuf (setq uniquify-managed nil))
211 (when dirname 236 (when dirname
212 (setq dirname (expand-file-name (directory-file-name dirname))) 237 (setq dirname (funcall uniquify-dirname-transform
238 (expand-file-name (directory-file-name dirname))))
213 (let ((fix-list (list (uniquify-make-item base dirname newbuf 239 (let ((fix-list (list (uniquify-make-item base dirname newbuf
214 nil))) 240 nil)))
215 items) 241 items)
@@ -268,10 +294,11 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
268 (if (memq major-mode uniquify-list-buffers-directory-modes) 294 (if (memq major-mode uniquify-list-buffers-directory-modes)
269 list-buffers-directory)))) 295 list-buffers-directory))))
270 (when filename 296 (when filename
271 (directory-file-name 297 (funcall uniquify-dirname-transform
272 (file-name-directory 298 (directory-file-name
273 (expand-file-name 299 (file-name-directory
274 (directory-file-name filename)))))))) 300 (expand-file-name
301 (directory-file-name filename)))))))))
275 302
276(defun uniquify-rerationalize-w/o-cb (fix-list) 303(defun uniquify-rerationalize-w/o-cb (fix-list)
277 "Re-rationalize the buffers in FIX-LIST, but ignoring `current-buffer'." 304 "Re-rationalize the buffers in FIX-LIST, but ignoring `current-buffer'."
diff --git a/test/lisp/uniquify-tests.el b/test/lisp/uniquify-tests.el
index abd61fa3504..e533c4b644c 100644
--- a/test/lisp/uniquify-tests.el
+++ b/test/lisp/uniquify-tests.el
@@ -88,6 +88,21 @@
88 '("a/dir/" "b/dir/"))) 88 '("a/dir/" "b/dir/")))
89 (mapc #'kill-buffer bufs))))) 89 (mapc #'kill-buffer bufs)))))
90 90
91(ert-deftest uniquify-home ()
92 "uniquify works, albeit confusingly, in the presence of directories named \"~\""
93 (let (bufs)
94 (save-excursion
95 (push (find-file-noselect "~") bufs)
96 (push (find-file-noselect "./~") bufs)
97 (should (equal (mapcar #'buffer-name bufs)
98 '("~<test>" "~<>")))
99 (push (find-file-noselect "~/foo") bufs)
100 (push (find-file-noselect "./~/foo") bufs)
101 (should (equal (mapcar #'buffer-name bufs)
102 '("foo<~>" "foo</nonexistent>" "~<test>" "~<>")))
103 (while bufs
104 (kill-buffer (pop bufs))))))
105
91(ert-deftest uniquify-rename-to-dir () 106(ert-deftest uniquify-rename-to-dir ()
92 "Giving a buffer a name which matches a directory doesn't rename the buffer" 107 "Giving a buffer a name which matches a directory doesn't rename the buffer"
93 (let ((uniquify-buffer-name-style 'forward) 108 (let ((uniquify-buffer-name-style 'forward)
@@ -125,5 +140,23 @@ uniquify-trailing-separator-p is ignored"
125 (should (equal (buffer-name) "| foo")) 140 (should (equal (buffer-name) "| foo"))
126 (kill-buffer))) 141 (kill-buffer)))
127 142
143(require 'project)
144(ert-deftest uniquify-project-transform ()
145 "`project-uniquify-dirname-transform' works"
146 (let ((uniquify-dirname-transform #'project-uniquify-dirname-transform)
147 (project-vc-name "foo1/bar")
148 bufs)
149 (save-excursion
150 (should (file-exists-p "../README"))
151 (push (find-file-noselect "../README") bufs)
152 (push (find-file-noselect "other/README") bufs)
153 (should (equal (mapcar #'buffer-name bufs)
154 '("README<other>" "README<bar>")))
155 (push (find-file-noselect "foo2/bar/README") bufs)
156 (should (equal (mapcar #'buffer-name bufs)
157 '("README<foo2/bar>" "README<other>" "README<foo1/bar>")))
158 (while bufs
159 (kill-buffer (pop bufs))))))
160
128(provide 'uniquify-tests) 161(provide 'uniquify-tests)
129;;; uniquify-tests.el ends here 162;;; uniquify-tests.el ends here