Mercurial > hg > xemacs-beta
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 |