Mercurial > hg > xemacs-beta
diff lisp/utils/uniquify.el @ 30:ec9a17fef872 r19-15b98
Import from CVS: tag r19-15b98
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:52:29 +0200 |
parents | ac2d302a0011 |
children | 131b0175ea99 |
line wrap: on
line diff
--- a/lisp/utils/uniquify.el Mon Aug 13 08:51:58 2007 +0200 +++ b/lisp/utils/uniquify.el Mon Aug 13 08:52:29 2007 +0200 @@ -1,10 +1,11 @@ ;;; uniquify.el --- unique buffer names dependent on file name -;; Copyright (c) 1989, 1995 Free Software Foundation, Inc. +;; Copyright (c) 1989, 1995, 1996, 1997 Free Software Foundation, Inc. ;; Author: Dick King <king@reasoning.com> ;; Maintainer: Michael Ernst <mernst@theory.lcs.mit.edu> ;; Created: 15 May 86 +;; Time-stamp: <97/03/03 17:16:23 mernst> ;; This file is part of GNU Emacs. @@ -19,9 +20,8 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;;; Commentary: @@ -34,12 +34,17 @@ ;; Makefile|zaphod, respectively (instead of Makefile and Makefile<2>). ;; Other buffer name styles are also available. -;; To use this file, just load it. +;; To use this file, just load it; or add (require 'uniquify) to your .emacs. ;; To disable it after loading, set variable uniquify-buffer-name-style to nil. ;; For other options, see "User-visible variables", below. -;; A version of uniquify.el that works under Emacs 18, Emacs 19, XEmacs, -;; and InfoDock is available from the maintainer. +;; uniquify.el works under Emacs 18, Emacs 19, XEmacs, and InfoDock. + +;; Doesn't correctly handle buffer names created by M-x write-file in Emacs 18. +;; Doesn't work under NT when backslash is used as a path separator (forward +;; slash path separator works fine). To fix, check system-type against +;; 'windows-nt, write a routine that breaks paths down into components. +;; (Surprisingly, there isn't one built in.) ;;; Change Log: @@ -59,13 +64,17 @@ ;; uniquify-buffer-name-style; add 'forward and 'post-forward-angle-brackets ;; styles; remove uniquify-reverse-dir-content-p; add ;; uniquify-trailing-separator-p. mernst 4 Aug 95 +;; Don't call expand-file-name on nil. mernst 7 Jan 96 +;; Check whether list-buffers-directory is bound. mernst 11 Oct 96 +;; Ignore non-file non-dired buffers. Colin Rafferty <craffert@ml.com> 3 Mar 97 ;; Valuable feedback was provided by ;; Paul Smith <psmith@baynetworks.com>, ;; Alastair Burt <burt@dfki.uni-kl.de>, ;; Bob Weiner <weiner@footloose.sps.mot.com>, ;; Albert L. Ting <alt@vlibs.com>, -;; gyro@reasoning.com. +;; gyro@reasoning.com, +;; Bryan O'Sullivan <bos@eng.sun.com>. ;;; Code: @@ -148,8 +157,8 @@ (while buffers (let* ((buffer (car buffers)) (bfn (if (eq buffer newbuf) - (and newbuffile - (expand-file-name newbuffile)) + (and newbuffile + (expand-file-name newbuffile)) (uniquify-buffer-file-name buffer))) (rawname (and bfn (file-name-nondirectory bfn))) (deserving (and rawname @@ -172,11 +181,23 @@ ;; uniquify's version of buffer-file-name (defun uniquify-buffer-file-name (buffer) "Return name of file BUFFER is visiting, or nil if none. -Works on dired buffers as well as ordinary file-visiting buffers." +Works on dired buffers as well as ordinary file-visiting buffers, +but no others." (or (buffer-file-name buffer) - (save-excursion - (set-buffer buffer) - list-buffers-directory))) + (and (featurep 'dired) + (save-excursion + (set-buffer buffer) + (and + (eq major-mode 'dired-mode) ; do nothing if not a dired buffer + (if (boundp 'list-buffers-directory) ; XEmacs mightn't define this + list-buffers-directory + ;; don't use default-directory if dired-directory is nil + (and dired-directory + (expand-file-name + (directory-file-name + (if (consp dired-directory) + (car dired-directory) + dired-directory)))))))))) (defun uniquify-fix-list-filename-lessp (fixlist1 fixlist2) (uniquify-filename-lessp @@ -316,69 +337,149 @@ ;;; Hooks from the rest of Emacs -;; Emacs 19 (Emacs or XEmacs) +(cond + ((string-match "^19" emacs-version) + ;; Emacs 19 (Emacs or XEmacs) + + ;; The logical place to put all this code is in generate-new-buffer-name. + ;; It's written in C, so we would add a generate-new-buffer-name-function + ;; which, if non-nil, would be called instead of the C. One problem with + ;; that is that generate-new-buffer-name takes a potential buffer name as + ;; its argument -- not other information, such as what file the buffer will + ;; visit. -;; The logical place to put all this code is in generate-new-buffer-name. -;; It's written in C, so we would add a generate-new-buffer-name-function -;; which, if non-nil, would be called instead of the C. One problem with -;; that is that generate-new-buffer-name takes a potential buffer name as -;; its argument -- not other information, such as what file the buffer will -;; visit. + ;; The below solution works because generate-new-buffer-name is called + ;; only by rename-buffer (which, as of 19.29, is never called from C) and + ;; generate-new-buffer, which is called only by Lisp functions + ;; create-file-buffer and rename-uniquely. Rename-uniquely generally + ;; isn't used for buffers visiting files, so it's sufficient to hook + ;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't + ;; sufficient.) + + (defadvice rename-buffer (after rename-buffer-uniquify activate) + "Uniquify buffer names with parts of directory name." + (if (and uniquify-buffer-name-style + ;; UNIQUE argument + (ad-get-arg 1)) + (progn + (if uniquify-after-kill-buffer-p + ;; call with no argument; rationalize vs. old name as well as new + (uniquify-rationalize-file-buffer-names) + ;; call with argument: rationalize vs. new name only + (uniquify-rationalize-file-buffer-names + (uniquify-buffer-file-name (current-buffer)) (current-buffer))) + (setq ad-return-value (buffer-name (current-buffer)))))) -;; The below solution works because generate-new-buffer-name is called -;; only by rename-buffer (which, as of 19.29, is never called from C) and -;; generate-new-buffer, which is called only by Lisp functions -;; create-file-buffer and rename-uniquely. Rename-uniquely generally -;; isn't used for buffers visiting files, so it's sufficient to hook -;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't -;; sufficient.) + (defadvice create-file-buffer (after create-file-buffer-uniquify activate) + "Uniquify buffer names with parts of directory name." + (if uniquify-buffer-name-style + (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value))) + + ;; Buffer deletion + ;; Rerationalize after a buffer is killed, to reduce coinciding buffer names. + ;; This mechanism uses `kill-buffer-hook', which runs *before* deletion. + ;; That means that the kill-buffer-hook function cannot just delete the + ;; buffer -- it has to set something to do the rationalization *later*. + ;; It actually puts another function on `post-command-hook'. This other + ;; function runs the rationalization and then removes itself from the hook. + ;; Is there a better way to accomplish this? + ;; (This ought to set some global variables so the work is done only for + ;; buffers with names similar to the deleted buffer. -MDE) -(defadvice rename-buffer (after rename-buffer-uniquify activate) - "Uniquify buffer names with parts of directory name." - (if (and uniquify-buffer-name-style - ;; UNIQUE argument - (ad-get-arg 1)) - (progn - (if uniquify-after-kill-buffer-p - ;; call with no argument; rationalize vs. old name as well as new - (uniquify-rationalize-file-buffer-names) - ;; call with argument: rationalize vs. new name only - (uniquify-rationalize-file-buffer-names - (uniquify-buffer-file-name (current-buffer)) (current-buffer))) - (setq ad-return-value (buffer-name (current-buffer)))))) + (cond + ((or (not (string-lessp emacs-version "19.28")) + (and (string-match "XEmacs" emacs-version) + (not (string-lessp emacs-version "19.12")))) + ;; Emacs 19.28 or later, or XEmacs (19.12 or later; is that necessary?) + (defun delay-uniquify-rationalize-file-buffer-names () + "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'. +For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion." + (if (and uniquify-buffer-name-style + uniquify-after-kill-buffer-p) + (add-hook 'post-command-hook + 'delayed-uniquify-rationalize-file-buffer-names))) + (defun delayed-uniquify-rationalize-file-buffer-names () + "Rerationalize buffer names and remove self from `post-command-hook'. +See also `delay-rationalize-file-buffer-names' for hook setter." + (uniquify-rationalize-file-buffer-names) + (remove-hook 'post-command-hook + 'delayed-uniquify-rationalize-file-buffer-names)) -(defadvice create-file-buffer (after create-file-buffer-uniquify activate) - "Uniquify buffer names with parts of directory name." - (if uniquify-buffer-name-style - (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value))) + (add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names)) + (t + ;; GNU Emacs 19.01 through 19.27 + ;; Before version 19.28, {pre,post}-command-hook was unable to set itself. + + (defvar uniquify-post-command-p nil + "Set to trigger re-rationalization of buffer names by function on +`post-command-hook'. Used by kill-buffer-rationalization mechanism.") + + (defun uniquify-post-command-rerationalization () + "Set variable so buffer names may be rationalized by `post-command-hook'. -;; Buffer deletion -;; Rerationalize after a buffer is killed, to reduce coinciding buffer names. -;; This mechanism uses `kill-buffer-hook', which runs *before* deletion. -;; That means that the kill-buffer-hook function cannot just delete the -;; buffer -- it has to set something to do the rationalization *later*. -;; It actually puts another function on `post-command-hook'. This other -;; function runs the rationalization and then removes itself from the hook. -;; Is there a better way to accomplish this? -;; (This ought to set some global variables so the work is done only for -;; buffers with names similar to the deleted buffer. -MDE) +See variables `uniquify-post-command-p', `uniquify-buffer-name-style', and +`uniquify-after-kill-buffer-p'." + (if (and uniquify-buffer-name-style + uniquify-after-kill-buffer-p) + (setq uniquify-post-command-p + ;; Set the buffer name, so, once the delimiter character + ;; is parameterized, we could selectively rationalize just + ;; related buffer names. + (cons (buffer-name) uniquify-post-command-p)))) + (defun uniquify-rationalize-after-buffer-kill () + "Via `post-command-hook', rerationalize buffer names after kill-buffer. + +Checks `uniquify-post-command-p', which should be set by +`uniquify-post-command-rerationalization' function on `kill-buffer-hook'." + (if uniquify-post-command-p + (progn (if (and uniquify-buffer-name-style + uniquify-after-kill-buffer-p) + (uniquify-rationalize-file-buffer-names)) + (setq uniquify-post-command-p nil)))) + + (add-hook 'kill-buffer-hook 'uniquify-post-command-rerationalization) + (add-hook 'post-command-hook 'uniquify-rationalize-after-buffer-kill)) + )) + (t + ;; Emacs 18: redefine create-file-buffer and dired-find-buffer. -(defun delay-uniquify-rationalize-file-buffer-names () - "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'. -For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion." - (if (and uniquify-buffer-name-style - uniquify-after-kill-buffer-p) - (add-hook 'post-command-hook - 'delayed-uniquify-rationalize-file-buffer-names))) + ;; Since advice.el can run in Emacs 18 as well as Emacs 19, we could use + ;; advice here, too, if it is available; but it's not worth it, since + ;; Emacs 18 is obsolescent anyway. -(defun delayed-uniquify-rationalize-file-buffer-names () - "Rerationalize buffer names and remove self from `post-command-hook'. -See also `delay-rationalize-file-buffer-names' for hook setter." - (uniquify-rationalize-file-buffer-names) - (remove-hook 'post-command-hook - 'delayed-uniquify-rationalize-file-buffer-names)) + (defun create-file-buffer (filename) ;from files.el + "Create a suitably named buffer for visiting FILENAME, and return it." + (let ((base (file-name-nondirectory filename))) + (if (string= base "") + (setq base filename)) + (if (and (get-buffer base) + uniquify-ask-about-buffer-names-p) + (get-buffer-create + (let ((tem (read-string (format + "Buffer name \"%s\" is in use; type a new name, or Return to clobber: " + base)))) + (if (equal tem "") base tem))) + (let ((buf (generate-new-buffer base))) + (if uniquify-buffer-name-style + (uniquify-rationalize-file-buffer-names filename buf)) + buf)))) -(add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names) + (defun dired-find-buffer (dirname) ;from dired.el + (let ((blist (buffer-list)) + found) + (while blist + (save-excursion + (set-buffer (car blist)) + (if (and (eq major-mode 'dired-mode) + (equal dired-directory dirname)) + (setq found (car blist) + blist nil) + (setq blist (cdr blist))))) + (or found + (progn (if (string-match "/$" dirname) + (setq dirname (substring dirname 0 -1))) + (create-file-buffer (if uniquify-buffer-name-style + dirname + (file-name-nondirectory dirname))))))))) ;;; uniquify.el ends here -