comparison 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
comparison
equal deleted inserted replaced
29:7976500f47f9 30:ec9a17fef872
1 ;;; uniquify.el --- unique buffer names dependent on file name 1 ;;; uniquify.el --- unique buffer names dependent on file name
2 2
3 ;; Copyright (c) 1989, 1995 Free Software Foundation, Inc. 3 ;; Copyright (c) 1989, 1995, 1996, 1997 Free Software Foundation, Inc.
4 4
5 ;; Author: Dick King <king@reasoning.com> 5 ;; Author: Dick King <king@reasoning.com>
6 ;; Maintainer: Michael Ernst <mernst@theory.lcs.mit.edu> 6 ;; Maintainer: Michael Ernst <mernst@theory.lcs.mit.edu>
7 ;; Created: 15 May 86 7 ;; Created: 15 May 86
8 ;; Time-stamp: <97/03/03 17:16:23 mernst>
8 9
9 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
10 11
11 ;; GNU Emacs is free software; you can redistribute it and/or modify 12 ;; GNU Emacs is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by 13 ;; it under the terms of the GNU General Public License as published by
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details. 20 ;; GNU General Public License for more details.
20 21
21 ;; You should have received a copy of the GNU General Public License 22 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the 23 ;; along with GNU Emacs; see the file COPYING. If not, write to
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 24 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 ;; Boston, MA 02111-1307, USA.
25 25
26 ;;; Commentary: 26 ;;; Commentary:
27 27
28 ;; Emacs's standard method for making buffer names unique adds <2>, <3>, 28 ;; Emacs's standard method for making buffer names unique adds <2>, <3>,
29 ;; etc. to the end of (all but one of) the buffers. This file replaces 29 ;; etc. to the end of (all but one of) the buffers. This file replaces
32 ;; are unique. For instance, buffers visiting /u/mernst/tmp/Makefile and 32 ;; are unique. For instance, buffers visiting /u/mernst/tmp/Makefile and
33 ;; /usr/projects/zaphod/Makefile would be named Makefile|tmp and 33 ;; /usr/projects/zaphod/Makefile would be named Makefile|tmp and
34 ;; Makefile|zaphod, respectively (instead of Makefile and Makefile<2>). 34 ;; Makefile|zaphod, respectively (instead of Makefile and Makefile<2>).
35 ;; Other buffer name styles are also available. 35 ;; Other buffer name styles are also available.
36 36
37 ;; To use this file, just load it. 37 ;; To use this file, just load it; or add (require 'uniquify) to your .emacs.
38 ;; To disable it after loading, set variable uniquify-buffer-name-style to nil. 38 ;; To disable it after loading, set variable uniquify-buffer-name-style to nil.
39 ;; For other options, see "User-visible variables", below. 39 ;; For other options, see "User-visible variables", below.
40 40
41 ;; A version of uniquify.el that works under Emacs 18, Emacs 19, XEmacs, 41 ;; uniquify.el works under Emacs 18, Emacs 19, XEmacs, and InfoDock.
42 ;; and InfoDock is available from the maintainer. 42
43 ;; Doesn't correctly handle buffer names created by M-x write-file in Emacs 18.
44 ;; Doesn't work under NT when backslash is used as a path separator (forward
45 ;; slash path separator works fine). To fix, check system-type against
46 ;; 'windows-nt, write a routine that breaks paths down into components.
47 ;; (Surprisingly, there isn't one built in.)
43 48
44 ;;; Change Log: 49 ;;; Change Log:
45 50
46 ;; Originally by Dick King <king@reasoning.com> 15 May 86 51 ;; Originally by Dick King <king@reasoning.com> 15 May 86
47 ;; Converted for Emacs 18 by Stephen Gildea <gildea@lcs.mit.edu> 52 ;; Converted for Emacs 18 by Stephen Gildea <gildea@lcs.mit.edu>
57 ;; add uniquify-ask-about-buffer-names-p. king, mernst 13 Jun 95 62 ;; add uniquify-ask-about-buffer-names-p. king, mernst 13 Jun 95
58 ;; Prefix functions by "uniquify-..."; rename mnemonic-buffer-names to 63 ;; Prefix functions by "uniquify-..."; rename mnemonic-buffer-names to
59 ;; uniquify-buffer-name-style; add 'forward and 'post-forward-angle-brackets 64 ;; uniquify-buffer-name-style; add 'forward and 'post-forward-angle-brackets
60 ;; styles; remove uniquify-reverse-dir-content-p; add 65 ;; styles; remove uniquify-reverse-dir-content-p; add
61 ;; uniquify-trailing-separator-p. mernst 4 Aug 95 66 ;; uniquify-trailing-separator-p. mernst 4 Aug 95
67 ;; Don't call expand-file-name on nil. mernst 7 Jan 96
68 ;; Check whether list-buffers-directory is bound. mernst 11 Oct 96
69 ;; Ignore non-file non-dired buffers. Colin Rafferty <craffert@ml.com> 3 Mar 97
62 70
63 ;; Valuable feedback was provided by 71 ;; Valuable feedback was provided by
64 ;; Paul Smith <psmith@baynetworks.com>, 72 ;; Paul Smith <psmith@baynetworks.com>,
65 ;; Alastair Burt <burt@dfki.uni-kl.de>, 73 ;; Alastair Burt <burt@dfki.uni-kl.de>,
66 ;; Bob Weiner <weiner@footloose.sps.mot.com>, 74 ;; Bob Weiner <weiner@footloose.sps.mot.com>,
67 ;; Albert L. Ting <alt@vlibs.com>, 75 ;; Albert L. Ting <alt@vlibs.com>,
68 ;; gyro@reasoning.com. 76 ;; gyro@reasoning.com,
77 ;; Bryan O'Sullivan <bos@eng.sun.com>.
69 78
70 79
71 ;;; Code: 80 ;;; Code:
72 81
73 (provide 'uniquify) 82 (provide 'uniquify)
146 (depth uniquify-min-dir-content)) 155 (depth uniquify-min-dir-content))
147 (let ((buffers (buffer-list))) 156 (let ((buffers (buffer-list)))
148 (while buffers 157 (while buffers
149 (let* ((buffer (car buffers)) 158 (let* ((buffer (car buffers))
150 (bfn (if (eq buffer newbuf) 159 (bfn (if (eq buffer newbuf)
151 (and newbuffile 160 (and newbuffile
152 (expand-file-name newbuffile)) 161 (expand-file-name newbuffile))
153 (uniquify-buffer-file-name buffer))) 162 (uniquify-buffer-file-name buffer)))
154 (rawname (and bfn (file-name-nondirectory bfn))) 163 (rawname (and bfn (file-name-nondirectory bfn)))
155 (deserving (and rawname 164 (deserving (and rawname
156 (or (not newbuffile) 165 (or (not newbuffile)
157 (equal rawname 166 (equal rawname
170 (mapcar 'uniquify-unrationalized-buffer fix-list))) 179 (mapcar 'uniquify-unrationalized-buffer fix-list)))
171 180
172 ;; uniquify's version of buffer-file-name 181 ;; uniquify's version of buffer-file-name
173 (defun uniquify-buffer-file-name (buffer) 182 (defun uniquify-buffer-file-name (buffer)
174 "Return name of file BUFFER is visiting, or nil if none. 183 "Return name of file BUFFER is visiting, or nil if none.
175 Works on dired buffers as well as ordinary file-visiting buffers." 184 Works on dired buffers as well as ordinary file-visiting buffers,
185 but no others."
176 (or (buffer-file-name buffer) 186 (or (buffer-file-name buffer)
177 (save-excursion 187 (and (featurep 'dired)
178 (set-buffer buffer) 188 (save-excursion
179 list-buffers-directory))) 189 (set-buffer buffer)
190 (and
191 (eq major-mode 'dired-mode) ; do nothing if not a dired buffer
192 (if (boundp 'list-buffers-directory) ; XEmacs mightn't define this
193 list-buffers-directory
194 ;; don't use default-directory if dired-directory is nil
195 (and dired-directory
196 (expand-file-name
197 (directory-file-name
198 (if (consp dired-directory)
199 (car dired-directory)
200 dired-directory))))))))))
180 201
181 (defun uniquify-fix-list-filename-lessp (fixlist1 fixlist2) 202 (defun uniquify-fix-list-filename-lessp (fixlist1 fixlist2)
182 (uniquify-filename-lessp 203 (uniquify-filename-lessp
183 (uniquify-fix-list-filename fixlist1) (uniquify-fix-list-filename fixlist2))) 204 (uniquify-fix-list-filename fixlist1) (uniquify-fix-list-filename fixlist2)))
184 205
314 (apply (function concat) sofar))) 335 (apply (function concat) sofar)))
315 336
316 337
317 ;;; Hooks from the rest of Emacs 338 ;;; Hooks from the rest of Emacs
318 339
319 ;; Emacs 19 (Emacs or XEmacs) 340 (cond
320 341 ((string-match "^19" emacs-version)
321 ;; The logical place to put all this code is in generate-new-buffer-name. 342 ;; Emacs 19 (Emacs or XEmacs)
322 ;; It's written in C, so we would add a generate-new-buffer-name-function 343
323 ;; which, if non-nil, would be called instead of the C. One problem with 344 ;; The logical place to put all this code is in generate-new-buffer-name.
324 ;; that is that generate-new-buffer-name takes a potential buffer name as 345 ;; It's written in C, so we would add a generate-new-buffer-name-function
325 ;; its argument -- not other information, such as what file the buffer will 346 ;; which, if non-nil, would be called instead of the C. One problem with
326 ;; visit. 347 ;; that is that generate-new-buffer-name takes a potential buffer name as
327 348 ;; its argument -- not other information, such as what file the buffer will
328 ;; The below solution works because generate-new-buffer-name is called 349 ;; visit.
329 ;; only by rename-buffer (which, as of 19.29, is never called from C) and 350
330 ;; generate-new-buffer, which is called only by Lisp functions 351 ;; The below solution works because generate-new-buffer-name is called
331 ;; create-file-buffer and rename-uniquely. Rename-uniquely generally 352 ;; only by rename-buffer (which, as of 19.29, is never called from C) and
332 ;; isn't used for buffers visiting files, so it's sufficient to hook 353 ;; generate-new-buffer, which is called only by Lisp functions
333 ;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't 354 ;; create-file-buffer and rename-uniquely. Rename-uniquely generally
334 ;; sufficient.) 355 ;; isn't used for buffers visiting files, so it's sufficient to hook
335 356 ;; rename-buffer and create-file-buffer. (Setting find-file-hooks isn't
336 (defadvice rename-buffer (after rename-buffer-uniquify activate) 357 ;; sufficient.)
337 "Uniquify buffer names with parts of directory name." 358
338 (if (and uniquify-buffer-name-style 359 (defadvice rename-buffer (after rename-buffer-uniquify activate)
339 ;; UNIQUE argument 360 "Uniquify buffer names with parts of directory name."
340 (ad-get-arg 1)) 361 (if (and uniquify-buffer-name-style
341 (progn 362 ;; UNIQUE argument
342 (if uniquify-after-kill-buffer-p 363 (ad-get-arg 1))
343 ;; call with no argument; rationalize vs. old name as well as new 364 (progn
344 (uniquify-rationalize-file-buffer-names) 365 (if uniquify-after-kill-buffer-p
345 ;; call with argument: rationalize vs. new name only 366 ;; call with no argument; rationalize vs. old name as well as new
346 (uniquify-rationalize-file-buffer-names 367 (uniquify-rationalize-file-buffer-names)
347 (uniquify-buffer-file-name (current-buffer)) (current-buffer))) 368 ;; call with argument: rationalize vs. new name only
348 (setq ad-return-value (buffer-name (current-buffer)))))) 369 (uniquify-rationalize-file-buffer-names
349 370 (uniquify-buffer-file-name (current-buffer)) (current-buffer)))
350 (defadvice create-file-buffer (after create-file-buffer-uniquify activate) 371 (setq ad-return-value (buffer-name (current-buffer))))))
351 "Uniquify buffer names with parts of directory name." 372
352 (if uniquify-buffer-name-style 373 (defadvice create-file-buffer (after create-file-buffer-uniquify activate)
353 (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value))) 374 "Uniquify buffer names with parts of directory name."
354 375 (if uniquify-buffer-name-style
355 ;; Buffer deletion 376 (uniquify-rationalize-file-buffer-names (ad-get-arg 0) ad-return-value)))
356 ;; Rerationalize after a buffer is killed, to reduce coinciding buffer names. 377
357 ;; This mechanism uses `kill-buffer-hook', which runs *before* deletion. 378 ;; Buffer deletion
358 ;; That means that the kill-buffer-hook function cannot just delete the 379 ;; Rerationalize after a buffer is killed, to reduce coinciding buffer names.
359 ;; buffer -- it has to set something to do the rationalization *later*. 380 ;; This mechanism uses `kill-buffer-hook', which runs *before* deletion.
360 ;; It actually puts another function on `post-command-hook'. This other 381 ;; That means that the kill-buffer-hook function cannot just delete the
361 ;; function runs the rationalization and then removes itself from the hook. 382 ;; buffer -- it has to set something to do the rationalization *later*.
362 ;; Is there a better way to accomplish this? 383 ;; It actually puts another function on `post-command-hook'. This other
363 ;; (This ought to set some global variables so the work is done only for 384 ;; function runs the rationalization and then removes itself from the hook.
364 ;; buffers with names similar to the deleted buffer. -MDE) 385 ;; Is there a better way to accomplish this?
365 386 ;; (This ought to set some global variables so the work is done only for
366 (defun delay-uniquify-rationalize-file-buffer-names () 387 ;; buffers with names similar to the deleted buffer. -MDE)
367 "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'. 388
389 (cond
390 ((or (not (string-lessp emacs-version "19.28"))
391 (and (string-match "XEmacs" emacs-version)
392 (not (string-lessp emacs-version "19.12"))))
393 ;; Emacs 19.28 or later, or XEmacs (19.12 or later; is that necessary?)
394 (defun delay-uniquify-rationalize-file-buffer-names ()
395 "Add `delayed-uniquify-rationalize-file-buffer-names' to `post-command-hook'.
368 For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion." 396 For use on, eg, `kill-buffer-hook', to rationalize *after* buffer deletion."
369 (if (and uniquify-buffer-name-style 397 (if (and uniquify-buffer-name-style
370 uniquify-after-kill-buffer-p) 398 uniquify-after-kill-buffer-p)
371 (add-hook 'post-command-hook 399 (add-hook 'post-command-hook
372 'delayed-uniquify-rationalize-file-buffer-names))) 400 'delayed-uniquify-rationalize-file-buffer-names)))
373 401 (defun delayed-uniquify-rationalize-file-buffer-names ()
374 (defun delayed-uniquify-rationalize-file-buffer-names () 402 "Rerationalize buffer names and remove self from `post-command-hook'.
375 "Rerationalize buffer names and remove self from `post-command-hook'.
376 See also `delay-rationalize-file-buffer-names' for hook setter." 403 See also `delay-rationalize-file-buffer-names' for hook setter."
377 (uniquify-rationalize-file-buffer-names) 404 (uniquify-rationalize-file-buffer-names)
378 (remove-hook 'post-command-hook 405 (remove-hook 'post-command-hook
379 'delayed-uniquify-rationalize-file-buffer-names)) 406 'delayed-uniquify-rationalize-file-buffer-names))
380 407
381 (add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names) 408 (add-hook 'kill-buffer-hook 'delay-uniquify-rationalize-file-buffer-names))
409 (t
410 ;; GNU Emacs 19.01 through 19.27
411 ;; Before version 19.28, {pre,post}-command-hook was unable to set itself.
412
413 (defvar uniquify-post-command-p nil
414 "Set to trigger re-rationalization of buffer names by function on
415 `post-command-hook'. Used by kill-buffer-rationalization mechanism.")
416
417 (defun uniquify-post-command-rerationalization ()
418 "Set variable so buffer names may be rationalized by `post-command-hook'.
419
420 See variables `uniquify-post-command-p', `uniquify-buffer-name-style', and
421 `uniquify-after-kill-buffer-p'."
422 (if (and uniquify-buffer-name-style
423 uniquify-after-kill-buffer-p)
424 (setq uniquify-post-command-p
425 ;; Set the buffer name, so, once the delimiter character
426 ;; is parameterized, we could selectively rationalize just
427 ;; related buffer names.
428 (cons (buffer-name) uniquify-post-command-p))))
429 (defun uniquify-rationalize-after-buffer-kill ()
430 "Via `post-command-hook', rerationalize buffer names after kill-buffer.
431
432 Checks `uniquify-post-command-p', which should be set by
433 `uniquify-post-command-rerationalization' function on `kill-buffer-hook'."
434 (if uniquify-post-command-p
435 (progn (if (and uniquify-buffer-name-style
436 uniquify-after-kill-buffer-p)
437 (uniquify-rationalize-file-buffer-names))
438 (setq uniquify-post-command-p nil))))
439
440 (add-hook 'kill-buffer-hook 'uniquify-post-command-rerationalization)
441 (add-hook 'post-command-hook 'uniquify-rationalize-after-buffer-kill))
442 ))
443 (t
444 ;; Emacs 18: redefine create-file-buffer and dired-find-buffer.
445
446 ;; Since advice.el can run in Emacs 18 as well as Emacs 19, we could use
447 ;; advice here, too, if it is available; but it's not worth it, since
448 ;; Emacs 18 is obsolescent anyway.
449
450 (defun create-file-buffer (filename) ;from files.el
451 "Create a suitably named buffer for visiting FILENAME, and return it."
452 (let ((base (file-name-nondirectory filename)))
453 (if (string= base "")
454 (setq base filename))
455 (if (and (get-buffer base)
456 uniquify-ask-about-buffer-names-p)
457 (get-buffer-create
458 (let ((tem (read-string (format
459 "Buffer name \"%s\" is in use; type a new name, or Return to clobber: "
460 base))))
461 (if (equal tem "") base tem)))
462 (let ((buf (generate-new-buffer base)))
463 (if uniquify-buffer-name-style
464 (uniquify-rationalize-file-buffer-names filename buf))
465 buf))))
466
467 (defun dired-find-buffer (dirname) ;from dired.el
468 (let ((blist (buffer-list))
469 found)
470 (while blist
471 (save-excursion
472 (set-buffer (car blist))
473 (if (and (eq major-mode 'dired-mode)
474 (equal dired-directory dirname))
475 (setq found (car blist)
476 blist nil)
477 (setq blist (cdr blist)))))
478 (or found
479 (progn (if (string-match "/$" dirname)
480 (setq dirname (substring dirname 0 -1)))
481 (create-file-buffer (if uniquify-buffer-name-style
482 dirname
483 (file-name-nondirectory dirname)))))))))
382 484
383 ;;; uniquify.el ends here 485 ;;; uniquify.el ends here
384