comparison lisp/utils/uniquify.el @ 189:489f57a838ef r20-3b21

Import from CVS: tag r20-3b21
author cvs
date Mon, 13 Aug 2007 09:57:07 +0200
parents 8eaf7971accc
children 1f0dabaa0855
comparison
equal deleted inserted replaced
188:e29a8e7498d9 189:489f57a838ef
81 81
82 (provide 'uniquify) 82 (provide 'uniquify)
83 83
84 ;;; User-visible variables 84 ;;; User-visible variables
85 85
86 (progn 86 (defgroup uniquify nil
87 (defgroup uniquify nil 87 "Unique buffer names dependent on file name"
88 "Unique buffer names dependent on file name" 88 :group 'applications)
89 :group 'applications) 89
90 ) 90
91 91 (defcustom uniquify-buffer-name-style nil
92
93 (defcustom uniquify-buffer-name-style 'post-forward
94 "*If non-nil, buffer names are uniquified with parts of directory name. 92 "*If non-nil, buffer names are uniquified with parts of directory name.
95 The value determines the buffer name style and is one of `forward', 93 The value determines the buffer name style and is one of `forward',
96 `reverse', `post-forward' (the default), or `post-forward-angle-brackets'. 94 `reverse', `post-forward' (the default), or `post-forward-angle-brackets'.
97 For example, files `/foo/bar/mumble/name' and `/baz/quux/mumble/name' 95 For example, files `/foo/bar/mumble/name' and `/baz/quux/mumble/name'
98 would have the following buffer names in the various styles: 96 would have the following buffer names in the various styles:
104 :type '(radio (const forward) 102 :type '(radio (const forward)
105 (const reverse) 103 (const reverse)
106 (const post-forward) 104 (const post-forward)
107 (const podt-forward-angle-brackets) 105 (const podt-forward-angle-brackets)
108 (const nil)) 106 (const nil))
107 :require 'uniquify
109 :group 'uniquify) 108 :group 'uniquify)
110 109
111 (defcustom uniquify-after-kill-buffer-p nil 110 (defcustom uniquify-after-kill-buffer-p nil
112 "*If non-nil, rerationalize buffer names after a buffer has been killed. 111 "*If non-nil, rerationalize buffer names after a buffer has been killed.
113 This can be dangerous if Emacs Lisp code is keeping track of buffers by their 112 This can be dangerous if Emacs Lisp code is keeping track of buffers by their
358 (apply (function concat) sofar))) 357 (apply (function concat) sofar)))
359 358
360 359
361 ;;; Hooks from the rest of Emacs 360 ;;; Hooks from the rest of Emacs
362 361
363 (cond 362 ;; The logical place to put all this code is in generate-new-buffer-name.
364 ((string-match "^\\(19\\|20\\)" emacs-version) 363 ;; It's written in C, so we would add a generate-new-buffer-name-function
365 ;; Emacs 19 (Emacs or XEmacs) 364 ;; which, if non-nil, would be called instead of the C. One problem with
366 365 ;; that is that generate-new-buffer-name takes a potential buffer name as
367 ;; The logical place to put all this code is in generate-new-buffer-name. 366 ;; its argument -- not other information, such as what file the buffer will
368 ;; It's written in C, so we would add a generate-new-buffer-name-function 367 ;; visit.
369 ;; which, if non-nil, would be called instead of the C. One problem with 368
370 ;; that is that generate-new-buffer-name takes a potential buffer name as 369 ;; The below solution works because generate-new-buffer-name is called
371 ;; its argument -- not other information, such as what file the buffer will 370 ;; only by rename-buffer (which, as of 19.29, is never called from C) and
372 ;; visit. 371 ;; generate-new-buffer, which is called only by Lisp functions
373 372 ;; create-file-buffer and rename-uniquely. Rename-uniquely generally
374 ;; The below solution works because generate-new-buffer-name is called 373 ;; isn't used for buffers visiting files, so it's sufficient to hook
375 ;; only by rename-buffer (which, as of 19.29, is never called from C) and 374 ;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't
376 ;; generate-new-buffer, which is called only by Lisp functions 375 ;; sufficient.)
377 ;; create-file-buffer and rename-uniquely. Rename-uniquely generally 376
378 ;; isn't used for buffers visiting files, so it's sufficient to hook 377 (defadvice rename-buffer (after rename-buffer-uniquify activate)
379 ;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't 378 "Uniquify buffer names with parts of directory name."
380 ;; sufficient.) 379 (if (and uniquify-buffer-name-style
381 380 ;; UNIQUE argument
382 (defadvice rename-buffer (after rename-buffer-uniquify activate) 381 (ad-get-arg 1))
383 "Uniquify buffer names with parts of directory name." 382 (progn
384 (if (and uniquify-buffer-name-style 383 (if uniquify-after-kill-buffer-p
385 ;; UNIQUE argument 384 ;; call with no argument; rationalize vs. old name as well as new
386 (ad-get-arg 1)) 385 (uniquify-rationalize-file-buffer-names)
387 (progn 386 ;; call with argument: rationalize vs. new name only
388 (if uniquify-after-kill-buffer-p 387 (uniquify-rationalize-file-buffer-names
389 ;; call with no argument; rationalize vs. old name as well as new 388 (uniquify-buffer-file-name (current-buffer)) (current-buffer)))
390 (uniquify-rationalize-file-buffer-names) 389 (setq ad-return-value (buffer-name (current-buffer))))))
391 ;; call with argument: rationalize vs. new name only 390
392 (uniquify-rationalize-file-buffer-names 391 (defadvice create-file-buffer (after create-file-buffer-uniquify activate)
393 (uniquify-buffer-file-name (current-buffer)) (current-buffer))) 392 "Uniquify buffer names with parts of directory name."
394 (setq ad-return-value (buffer-name (current-buffer)))))) 393 (if uniquify-buffer-name-style
395 394 (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value)))
396 (defadvice create-file-buffer (after create-file-buffer-uniquify activate) 395
397 "Uniquify buffer names with parts of directory name." 396 ;; Buffer deletion
398 (if uniquify-buffer-name-style 397 ;; Rerationalize after a buffer is killed, to reduce coinciding buffer names.
399 (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value))) 398 ;; This mechanism uses `kill-buffer-hook', which runs *before* deletion.
400 399 ;; That means that the kill-buffer-hook function cannot just delete the
401 ;; Buffer deletion 400 ;; buffer -- it has to set something to do the rationalization *later*.
402 ;; Rerationalize after a buffer is killed, to reduce coinciding buffer names. 401 ;; It actually puts another function on `post-command-hook'. This other
403 ;; This mechanism uses `kill-buffer-hook', which runs *before* deletion. 402 ;; function runs the rationalization and then removes itself from the hook.
404 ;; That means that the kill-buffer-hook function cannot just delete the 403 ;; Is there a better way to accomplish this?
405 ;; buffer -- it has to set something to do the rationalization *later*. 404 ;; (This ought to set some global variables so the work is done only for
406 ;; It actually puts another function on `post-command-hook'. This other 405 ;; buffers with names similar to the deleted buffer. -MDE)
407 ;; function runs the rationalization and then removes itself from the hook. 406
408 ;; Is there a better way to accomplish this? 407 ;; Emacs 19.28 or later, or XEmacs (19.12 or later; is that necessary?)
409 ;; (This ought to set some global variables so the work is done only for 408 (defun delay-uniquify-rationalize-file-buffer-names ()
410 ;; buffers with names similar to the deleted buffer. -MDE) 409 "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'.
411
412 (cond
413 ((or (not (string-lessp emacs-version "19.28"))
414 (and (string-match "XEmacs" emacs-version)
415 (not (string-lessp emacs-version "19.12"))))
416 ;; Emacs 19.28 or later, or XEmacs (19.12 or later; is that necessary?)
417 (defun delay-uniquify-rationalize-file-buffer-names ()
418 "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'.
419 For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion." 410 For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion."
420 (if (and uniquify-buffer-name-style 411 (if (and uniquify-buffer-name-style
421 uniquify-after-kill-buffer-p) 412 uniquify-after-kill-buffer-p)
422 (add-hook 'post-command-hook 413 (add-hook 'post-command-hook
423 'delayed-uniquify-rationalize-file-buffer-names))) 414 'delayed-uniquify-rationalize-file-buffer-names)))
424 (defun delayed-uniquify-rationalize-file-buffer-names () 415
425 "Rerationalize buffer names and remove self from `post-command-hook'. 416 (defun delayed-uniquify-rationalize-file-buffer-names ()
417 "Rerationalize buffer names and remove self from `post-command-hook'.
426 See also `delay-rationalize-file-buffer-names' for hook setter." 418 See also `delay-rationalize-file-buffer-names' for hook setter."
427 (uniquify-rationalize-file-buffer-names) 419 (uniquify-rationalize-file-buffer-names)
428 (remove-hook 'post-command-hook 420 (remove-hook 'post-command-hook
429 'delayed-uniquify-rationalize-file-buffer-names)) 421 'delayed-uniquify-rationalize-file-buffer-names))
430 422
431 (add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names)) 423 (add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names)
432 (t 424
433 ;; GNU Emacs 19.01 through 19.27
434 ;; Before version 19.28, {pre,post}-command-hook was unable to set itself.
435
436 (defvar uniquify-post-command-p nil
437 "Set to trigger re-rationalization of buffer names by function on
438 `post-command-hook'. Used by kill-buffer-rationalization mechanism.")
439
440 (defun uniquify-post-command-rerationalization ()
441 "Set variable so buffer names may be rationalized by `post-command-hook'.
442
443 See variables `uniquify-post-command-p', `uniquify-buffer-name-style', and
444 `uniquify-after-kill-buffer-p'."
445 (if (and uniquify-buffer-name-style
446 uniquify-after-kill-buffer-p)
447 (setq uniquify-post-command-p
448 ;; Set the buffer name, so, once the delimiter character
449 ;; is parameterized, we could selectively rationalize just
450 ;; related buffer names.
451 (cons (buffer-name) uniquify-post-command-p))))
452 (defun uniquify-rationalize-after-buffer-kill ()
453 "Via `post-command-hook', rerationalize buffer names after kill-buffer.
454
455 Checks `uniquify-post-command-p', which should be set by
456 `uniquify-post-command-rerationalization' function on `kill-buffer-hook'."
457 (if uniquify-post-command-p
458 (progn (if (and uniquify-buffer-name-style
459 uniquify-after-kill-buffer-p)
460 (uniquify-rationalize-file-buffer-names))
461 (setq uniquify-post-command-p nil))))
462
463 (add-hook 'kill-buffer-hook 'uniquify-post-command-rerationalization)
464 (add-hook 'post-command-hook 'uniquify-rationalize-after-buffer-kill))
465 ))
466 (t
467 ;; Emacs 18: redefine create-file-buffer and dired-find-buffer.
468
469 ;; Since advice.el can run in Emacs 18 as well as Emacs 19, we could use
470 ;; advice here, too, if it is available; but it's not worth it, since
471 ;; Emacs 18 is obsolescent anyway.
472
473 (defun create-file-buffer (filename) ;from files.el
474 "Create a suitably named buffer for visiting FILENAME, and return it."
475 (let ((base (file-name-nondirectory filename)))
476 (if (string= base "")
477 (setq base filename))
478 (if (and (get-buffer base)
479 uniquify-ask-about-buffer-names-p)
480 (get-buffer-create
481 (let ((tem (read-string (format
482 "Buffer name \"%s\" is in use; type a new name, or Return to clobber: "
483 base))))
484 (if (equal tem "") base tem)))
485 (let ((buf (generate-new-buffer base)))
486 (if uniquify-buffer-name-style
487 (uniquify-rationalize-file-buffer-names filename buf))
488 buf))))
489
490 (defun dired-find-buffer (dirname) ;from dired.el
491 (let ((blist (buffer-list))
492 found)
493 (while blist
494 (save-excursion
495 (set-buffer (car blist))
496 (if (and (eq major-mode 'dired-mode)
497 (equal dired-directory dirname))
498 (setq found (car blist)
499 blist nil)
500 (setq blist (cdr blist)))))
501 (or found
502 (progn (if (string-match "/$" dirname)
503 (setq dirname (substring dirname 0 -1)))
504 (create-file-buffer (if uniquify-buffer-name-style
505 dirname
506 (file-name-nondirectory dirname)))))))))
507 425
508 ;;; uniquify.el ends here 426 ;;; uniquify.el ends here