diff options
| author | Spencer Baugh | 2025-03-27 09:32:47 -0400 |
|---|---|---|
| committer | Dmitry Gutov | 2025-06-06 05:41:26 +0300 |
| commit | 79cd1cc30e0c9a5f058279dc6f618e5dc22a1945 (patch) | |
| tree | fa04fc599cb54c6ced9561f90a196b0bf72aeb0d | |
| parent | 8b0f5b05976a99e82e54d6c602d47a8668ccd9d5 (diff) | |
| download | emacs-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.el | 66 |
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 | |||
| 522 | The names are unique only among BUFFERS, and may conflict with other | ||
| 523 | buffers not in that list. | ||
| 524 | |||
| 525 | This does not rename the buffers or change any state; the unique name is | ||
| 526 | only 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 () |