aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSpencer Baugh2025-03-27 09:32:47 -0400
committerDmitry Gutov2025-06-06 05:41:26 +0300
commit79cd1cc30e0c9a5f058279dc6f618e5dc22a1945 (patch)
treefa04fc599cb54c6ced9561f90a196b0bf72aeb0d
parent8b0f5b05976a99e82e54d6c602d47a8668ccd9d5 (diff)
downloademacs-79cd1cc30e0c9a5f058279dc6f618e5dc22a1945.tar.gz
emacs-79cd1cc30e0c9a5f058279dc6f618e5dc22a1945.zip
Add uniquify-get-unique-names (bug#77312)
This new function provides an interface to uniquify.el which doesn't change the actual names of the buffers. This is useful for any commands which deal with a subset of all buffers; for example, project.el. * lisp/uniquify.el (uniquify-rationalize--generic): Add. (uniquify-rationalize, uniquify-rationalize-a-list) (uniquify-rationalize-conflicting-sublist): Explicitly pass RENAME-BUFFER-FN and GET-BUFFER-FN. (uniquify--stateless-curname, uniquify-get-unique-names): Add.
-rw-r--r--lisp/uniquify.el66
1 files changed, 55 insertions, 11 deletions
diff --git a/lisp/uniquify.el b/lisp/uniquify.el
index 1f5bdcd6224..6e25323bf5a 100644
--- a/lisp/uniquify.el
+++ b/lisp/uniquify.el
@@ -373,12 +373,17 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
373 ;; if there is a conflict. 373 ;; if there is a conflict.
374 (dolist (item fix-list) 374 (dolist (item fix-list)
375 (with-current-buffer (uniquify-item-buffer item) 375 (with-current-buffer (uniquify-item-buffer item)
376 (setq uniquify-managed fix-list)))
377 (uniquify-rationalize--generic fix-list #'uniquify-rename-buffer #'get-buffer))
378
379(defun uniquify-rationalize--generic (fix-list rename-buffer-fn get-buffer-fn)
380 (dolist (item fix-list)
381 (with-current-buffer (uniquify-item-buffer item)
376 ;; Refresh the dirnames and proposed names. 382 ;; Refresh the dirnames and proposed names.
377 (setf (uniquify-item-proposed item) 383 (setf (uniquify-item-proposed item)
378 (uniquify-get-proposed-name (uniquify-item-base item) 384 (uniquify-get-proposed-name (uniquify-item-base item)
379 (uniquify-item-dirname item) 385 (uniquify-item-dirname item)
380 nil)) 386 nil))))
381 (setq uniquify-managed fix-list)))
382 ;; Strip any shared last directory names of the dirname. 387 ;; Strip any shared last directory names of the dirname.
383 (when (and (cdr fix-list) uniquify-strip-common-suffix) 388 (when (and (cdr fix-list) uniquify-strip-common-suffix)
384 (let ((strip t)) 389 (let ((strip t))
@@ -404,13 +409,13 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
404 fix-list))))) 409 fix-list)))))
405 ;; If uniquify-min-dir-content is 0, this will end up just 410 ;; If uniquify-min-dir-content is 0, this will end up just
406 ;; passing fix-list to uniquify-rationalize-conflicting-sublist. 411 ;; passing fix-list to uniquify-rationalize-conflicting-sublist.
407 (uniquify-rationalize-a-list fix-list)) 412 (uniquify-rationalize-a-list fix-list nil rename-buffer-fn get-buffer-fn))
408 413
409(defun uniquify-item-greaterp (item1 item2) 414(defun uniquify-item-greaterp (item1 item2)
410 (string-lessp (uniquify-item-proposed item2) 415 (string-lessp (uniquify-item-proposed item2)
411 (uniquify-item-proposed item1))) 416 (uniquify-item-proposed item1)))
412 417
413(defun uniquify-rationalize-a-list (fix-list &optional depth) 418(defun uniquify-rationalize-a-list (fix-list depth rename-buffer-fn get-buffer-fn)
414 (unless depth (setq depth uniquify-min-dir-content)) 419 (unless depth (setq depth uniquify-min-dir-content))
415 (let (conflicting-sublist ; all elements have the same proposed name 420 (let (conflicting-sublist ; all elements have the same proposed name
416 (old-proposed "") 421 (old-proposed "")
@@ -421,12 +426,14 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
421 (setq proposed (uniquify-item-proposed item)) 426 (setq proposed (uniquify-item-proposed item))
422 (unless (equal proposed old-proposed) 427 (unless (equal proposed old-proposed)
423 (uniquify-rationalize-conflicting-sublist conflicting-sublist 428 (uniquify-rationalize-conflicting-sublist conflicting-sublist
424 old-proposed depth) 429 old-proposed depth
430 rename-buffer-fn get-buffer-fn)
425 (setq conflicting-sublist nil)) 431 (setq conflicting-sublist nil))
426 (push item conflicting-sublist) 432 (push item conflicting-sublist)
427 (setq old-proposed proposed)) 433 (setq old-proposed proposed))
428 (uniquify-rationalize-conflicting-sublist conflicting-sublist 434 (uniquify-rationalize-conflicting-sublist conflicting-sublist
429 old-proposed depth))) 435 old-proposed depth
436 rename-buffer-fn get-buffer-fn)))
430 437
431(defun uniquify-get-proposed-name (base dirname &optional depth) 438(defun uniquify-get-proposed-name (base dirname &optional depth)
432 (unless depth (setq depth uniquify-min-dir-content)) 439 (unless depth (setq depth uniquify-min-dir-content))
@@ -478,12 +485,12 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
478 485
479;; Deal with conflicting-sublist, all of whose elements have identical 486;; Deal with conflicting-sublist, all of whose elements have identical
480;; "base" components. 487;; "base" components.
481(defun uniquify-rationalize-conflicting-sublist (conf-list old-name depth) 488(defun uniquify-rationalize-conflicting-sublist (conf-list old-name depth rename-buffer-fn get-buffer-fn)
482 (when conf-list 489 (when conf-list
483 (if (or (cdr conf-list) 490 (if (or (cdr conf-list)
484 ;; Check that the proposed name doesn't conflict with some 491 ;; Check that the proposed name doesn't conflict with some
485 ;; existing buffer. 492 ;; existing buffer.
486 (let ((buf (get-buffer old-name))) 493 (let ((buf (funcall get-buffer-fn old-name)))
487 (and buf (not (eq buf (uniquify-item-buffer (car conf-list))))))) 494 (and buf (not (eq buf (uniquify-item-buffer (car conf-list)))))))
488 (when uniquify-possibly-resolvable 495 (when uniquify-possibly-resolvable
489 (setq uniquify-possibly-resolvable nil 496 (setq uniquify-possibly-resolvable nil
@@ -494,10 +501,9 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
494 (uniquify-item-base item) 501 (uniquify-item-base item)
495 (uniquify-item-dirname item) 502 (uniquify-item-dirname item)
496 depth))) 503 depth)))
497 (uniquify-rationalize-a-list conf-list depth)) 504 (uniquify-rationalize-a-list conf-list depth rename-buffer-fn get-buffer-fn))
498 (unless (string= old-name "") 505 (unless (string= old-name "")
499 (uniquify-rename-buffer (car conf-list) old-name))))) 506 (funcall rename-buffer-fn (car conf-list) old-name)))))
500
501 507
502(defun uniquify-rename-buffer (item newname) 508(defun uniquify-rename-buffer (item newname)
503 (let ((buffer (uniquify-item-buffer item))) 509 (let ((buffer (uniquify-item-buffer item)))
@@ -507,6 +513,44 @@ in `uniquify-list-buffers-directory-modes', otherwise returns nil."
507 ;; Pass the `unique' arg, so the advice doesn't mark it as unmanaged. 513 ;; Pass the `unique' arg, so the advice doesn't mark it as unmanaged.
508 (rename-buffer newname t)))))) 514 (rename-buffer newname t))))))
509 515
516(defvar-local uniquify--stateless-curname nil
517 "The current unique name of this buffer in `uniquify-get-unique-names'.")
518
519(defun uniquify-get-unique-names (buffers)
520 "Return an alist with a unique name for each buffer in BUFFERS.
521
522The names are unique only among BUFFERS, and may conflict with other
523buffers not in that list.
524
525This does not rename the buffers or change any state; the unique name is
526only present in the returned alist."
527 (let ((buffer-names (make-hash-table :size (length buffers) :test 'equal))
528 fix-lists-by-base)
529 (dolist (buf buffers)
530 (with-current-buffer buf
531 (setq uniquify--stateless-curname (buffer-name buf))
532 (puthash (buffer-name buf) buf buffer-names)
533 (when uniquify-managed
534 (let ((base (uniquify-item-base (car uniquify-managed))))
535 (push
536 (uniquify-make-item base (uniquify-buffer-file-name buf) buf nil)
537 (alist-get base fix-lists-by-base nil nil #'equal))))))
538 (dolist (pair fix-lists-by-base)
539 (uniquify-rationalize--generic
540 (cdr pair)
541 (lambda (item name) ; rename-buffer
542 (with-current-buffer (uniquify-item-buffer item)
543 (remhash uniquify--stateless-curname buffer-names)
544 (setq uniquify--stateless-curname name)
545 (puthash name (current-buffer) buffer-names)))
546 (lambda (name) ; get-buffer
547 (gethash name buffer-names)))))
548 (mapcar (lambda (buf)
549 (with-current-buffer buf
550 (prog1 (cons uniquify--stateless-curname buf)
551 (kill-local-variable 'uniquify--stateless-curname))))
552 buffers))
553
510;;; Hooks from the rest of Emacs 554;;; Hooks from the rest of Emacs
511 555
512(defun uniquify-maybe-rerationalize-w/o-cb () 556(defun uniquify-maybe-rerationalize-w/o-cb ()