Trailing whitespace deleted.
[bpt/emacs.git] / lisp / iswitchb.el
CommitLineData
6c56c80b 1;;; iswitchb.el --- switch between buffers using substrings
962a4216 2
ceba0dac 3;; Copyright (C) 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
962a4216 4
b2537dfa
RS
5;; Author: Stephen Eglen <stephen@gnu.org>
6;; Maintainer: Stephen Eglen <stephen@gnu.org>
19db4308 7;; Keywords: completion convenience
183040ff 8;; location: http://www.anc.ed.ac.uk/~stephen/emacs/
962a4216 9
6c56c80b
RS
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
962a4216
RS
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
6c56c80b 17;; GNU Emacs is distributed in the hope that it will be useful,
962a4216
RS
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING. If not, write to the
24;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25;; Boston, MA 02111-1307, USA.
26
c6e5b93f 27;;; Commentary:
962a4216 28
c6e5b93f 29;; Installation:
19db4308
DL
30;; To get the functions in this package bound to keys, use
31;; M-x iswitchb-mode or customize the option `iswitchb-mode'.
962a4216 32
962a4216 33;; As you type in a substring, the list of buffers currently matching
19db4308 34;; the substring is displayed as you type. The list is ordered so
962a4216
RS
35;; that the most recent buffers visited come at the start of the list.
36;; The buffer at the start of the list will be the one visited when
37;; you press return. By typing more of the substring, the list is
38;; narrowed down so that gradually the buffer you want will be at the
19db4308 39;; top of the list. Alternatively, you can use C-s and C-r to rotate
962a4216
RS
40;; buffer names in the list until the one you want is at the top of
41;; the list. Completion is also available so that you can see what is
42;; common to all of the matching buffers as you type.
43
44;; This code is similar to a couple of other packages. Michael R Cook
8097dd15 45;; <cook@sightpath.com> wrote a similar buffer switching package, but
962a4216
RS
46;; does exact matching rather than substring matching on buffer names.
47;; I also modified a couple of functions from icomplete.el to provide
48;; the completion feedback in the minibuffer.
49
19db4308 50;;; Example
962a4216 51
4d8ae757
RS
52;; If I have two buffers called "123456" and "123", with "123456" the
53;; most recent, when I use iswitchb, I first of all get presented with
54;; the list of all the buffers
962a4216 55;;
19db4308 56;; iswitch {123456,123}
962a4216
RS
57;;
58;; If I then press 2:
59;; iswitch 2[3]{123456,123}
60;;
61;; The list in {} are the matching buffers, most recent first (buffers
62;; visible in the current frame are put at the end of the list by
63;; default). At any time I can select the item at the head of the
64;; list by pressing RET. I can also bring the put the first element
65;; at the end of the list by pressing C-s, or put the last element at
66;; the head of the list by pressing C-r. The item in [] indicates
67;; what can be added to my input by pressing TAB. In this case, I
19db4308 68;; will get "3" added to my input. So, press TAB:
962a4216
RS
69;; iswitch 23{123456,123}
70;;
71;; At this point, I still have two matching buffers.
72;; If I want the first buffer in the list, I simply press RET. If I
73;; wanted the second in the list, I could press C-s to move it to the
74;; top of the list and then RET to select it.
75;;
4d8ae757 76;; However, if I type 4, I only have one match left:
962a4216
RS
77;; iswitch 234[123456] [Matched]
78;;
4d8ae757
RS
79;; Since there is only one matching buffer left, it is given in [] and we
80;; see the text [Matched] afterwards. I can now press TAB or RET to go
81;; to that buffer.
962a4216
RS
82;;
83;; If however, I now type "a":
84;; iswitch 234a [No match]
85;; There are no matching buffers. If I press RET or TAB, I can be
86;; prompted to create a new buffer called "234a".
87;;
88;; Of course, where this function comes in really useful is when you
89;; can specify the buffer using only a few keystrokes. In the above
90;; example, the quickest way to get to the "123456" buffer would be
ccd2f997 91;; just to type 4 and then RET (assuming there isn't any newer buffer
962a4216
RS
92;; with 4 in its name).
93
94;; To see a full list of all matching buffers in a separate buffer,
95;; hit ? or press TAB when there are no further completions to the
ccd2f997
KH
96;; substring. Repeated TAB presses will scroll you through this
97;; separate buffer.
962a4216 98
36a3b01c
RS
99;; The buffer at the head of the list can be killed by pressing C-k.
100;; If the buffer needs saving, you will be queried before the buffer
101;; is killed.
102
103;; If you find that the file you are after is not in a buffer, you can
104;; press C-x C-f to immediately drop into find-file.
105
4d8ae757
RS
106;; See the doc string of iswitchb for full keybindings and features.
107;; (describe-function 'iswitchb)
962a4216 108
8097dd15
GM
109;; Case matching: The case of strings when matching can be ignored or
110;; used depending on the value of iswitchb-case (default is the same
111;; as case-fold-search, normally t). Imagine you have the following
19db4308 112;; buffers:
8097dd15
GM
113;;
114;; INBOX *info* *scratch*
115;;
116;; Then these will be the matching buffers, depending on how you type
117;; the two letters `in' and the value of iswitchb-case:
118;;
119;; iswitchb-case user input | matching buffers
120;; ----------------------------------------------
19db4308
DL
121;; nil in | *info*
122;; t in | INBOX, *info*
123;; t IN | INBOX
124;; t In | [No match]
8097dd15 125
962a4216
RS
126;;; Customisation
127
128;; See the User Variables section below for easy ways to change the
36a3b01c
RS
129;; functionality of the program. These are accessible using the
130;; custom package.
8ae3ef6e 131;; To modify the keybindings, use something like:
962a4216 132;;
8ae3ef6e 133;;(add-hook 'iswitchb-mode-hook 'iswitchb-my-keys)
962a4216 134;;(defun iswitchb-my-keys ()
ccd2f997 135;; "Add my keybindings for iswitchb."
8ae3ef6e 136;; (define-key iswitchb-mode-map " " 'iswitchb-next-match))
962a4216 137;;
6b0cc1b5 138;; Seeing all the matching buffers
36a3b01c 139;;
962a4216 140;; If you have many matching buffers, they may not all fit onto one
f05b502e
GM
141;; line of the minibuffer. In Emacs 21, the variable
142;; `resize-mini-windows' controls how many lines of the minibuffer can
143;; be seen. For older versions of emacs, you can use
144;; `resize-minibuffer-mode'. You can also limit iswitchb so that it
962a4216
RS
145;; only shows a certain number of lines -- see the documentation for
146;; `iswitchb-minibuffer-setup-hook'.
147
6b0cc1b5 148;; Changing the list of buffers
962a4216
RS
149
150;; By default, the list of current buffers is most recent first,
151;; oldest last, with the exception that the buffers visible in the
152;; current frame are put at the end of the list. A hook exists to
153;; allow other functions to order the list. For example, if you add:
154;;
155;; (add-hook 'iswitchb-make-buflist-hook 'iswitchb-summaries-to-end)
156;;
157;; then all buffers matching "Summary" are moved to the end of the
158;; list. (I find this handy for keeping the INBOX Summary and so on
159;; out of the way.) It also moves buffers matching "output\*$" to the
160;; end of the list (these are created by AUC TeX when compiling.)
161;; Other functions could be made available which alter the list of
162;; matching buffers (either deleting or rearranging elements.)
163
164;; Font-Lock
165
166;; If you have font-lock loaded, the first matching buffer is
167;; highlighted. To switch this off, set (setq iswitchb-use-fonts nil)
168;; I don't use font-lock that much, so I've hardcoded the faces. If
169;; this is too harsh, let me know. Colouring of the matching buffer
170;; name was suggested by Carsten Dominik (dominik@strw.leidenuniv.nl)
171
6b0cc1b5 172;; Replacement for read-buffer
962a4216 173
ccd2f997
KH
174;; iswitchb-read-buffer has been written to be a drop in replacement
175;; for the normal buffer selection routine `read-buffer'. To use
c6e5b93f 176;; iswitch for all buffer selections in Emacs, add:
ccd2f997 177;; (setq read-buffer-function 'iswitchb-read-buffer)
4d8ae757 178;; (This variable was introduced in Emacs 20.3.)
c6e5b93f 179;; XEmacs users can get the same behaviour by doing:
19db4308 180;; (defalias 'read-buffer 'iswitchb-read-buffer)
c6e5b93f 181;; since `read-buffer' is defined in lisp.
36a3b01c 182
4d8ae757
RS
183;; Using iswitchb for other completion tasks.
184
a2c060f6 185;; Kin Cho (kin@neoscale.com) sent the following suggestion to use
f1180544 186;; iswitchb for other completion tasks.
4d8ae757
RS
187;;
188;; (defun my-icompleting-read (prompt choices)
189;; "Use iswitch as a completing-read replacement to choose from
190;; choices. PROMPT is a string to prompt with. CHOICES is a list of
191;; strings to choose from."
192;; (let ((iswitchb-make-buflist-hook
193;; (lambda ()
194;; (setq iswitchb-temp-buflist choices))))
195;; (iswitchb-read-buffer prompt)))
196;;
197;; example:
198;; (my-icompleting-read "Which fruit? " '
199;; ("apple" "pineapple" "pear" "bananas" "oranges") )
200
a2c060f6
PJ
201;; Kin Cho also suggested the following defun. Once you have a subset of
202;; matching buffers matching your current prompt, you can then press
203;; e.g. C-o to restrict matching to those buffers and clearing the prompt:
204;; (defun iswitchb-exclude-nonmatching()
205;; "Make iswitchb work on only the currently matching names."
206;; (interactive)
207;; (setq iswitchb-buflist iswitchb-matches)
208;; (setq iswitchb-rescan t)
209;; (delete-minibuffer-contents))
210;;
211;; (add-hook 'iswitchb-define-mode-map-hook
f1180544
JB
212;; '(lambda () (define-key
213;; iswitchb-mode-map "\C-o"
a2c060f6
PJ
214;; 'iswitchb-exclude-nonmatching)))
215
4d8ae757
RS
216;; Other lisp packages extend iswitchb behaviour to other tasks. See
217;; ido.el (by Kim Storm) and mcomplete.el (Yuji Minejima).
218
219;; Window managers: Switching frames/focus follows mouse; Sawfish.
220
221;; If you switch to a buffer that is visible in another frame,
222;; iswitchb can switch focus to that frame. If your window manager
223;; uses "click to focus" policy for window selection, you should also
224;; set focus-follows-mouse to nil.
225
226;; iswitch functionality has also been implemented for switching
227;; between windows in the Sawfish window manager.
228
6b0cc1b5
SE
229;; Regexp matching
230
231;; There is limited provision for regexp matching within iswitchb,
232;; enabled through `iswitchb-regexp'. This allows you to type `c$'
233;; for example and see all buffer names ending in `c'. This facility
234;; is quite limited though in two respects. First, you can't
235;; currently type in expressions like `[0-9]' directly -- you have to
236;; type them in when iswitchb-regexp is nil and then toggle on the
237;; regexp functionality. Likewise, don't enter an expression
238;; containing `\' in regexp mode. If you try, iswitchb gets confused,
239;; so just hit C-g and try again. Secondly, no completion mechanism
240;; is currently offered when regexp searching.
241
ccd2f997 242;;; TODO
36a3b01c 243
962a4216
RS
244;;; Acknowledgements
245
246;; Thanks to Jari Aalto <jari.aalto@poboxes.com> for help with the
247;; first version of this package, iswitch-buffer. Thanks also to many
248;; others for testing earlier versions.
249
250;;; Code:
251
c6e5b93f 252;; CL needed for cadr and last
181688f2
SE
253(if (not (and (fboundp 'cadr)
254 (fboundp 'last)))
255 (require 'cl))
c6e5b93f 256
36a3b01c
RS
257;; Set up the custom library.
258;; taken from http://www.dina.kvl.dk/~abraham/custom/
259(eval-and-compile
260 (condition-case ()
261 (require 'custom)
262 (error nil))
263 (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
264 nil ;; We've got what we needed
265 ;; We have the old custom-library, hack around it!
266 (defmacro defgroup (&rest args)
267 nil)
19db4308 268 (defmacro defcustom (var value doc &rest args)
b787fc05 269 `(defvar ,var ,value ,doc))))
36a3b01c 270
962a4216
RS
271;;; User Variables
272;;
273;; These are some things you might want to change.
274
36a3b01c 275(defgroup iswitchb nil
c6e5b93f 276 "Switch between buffers using substrings."
f5f727f8 277 :group 'convenience
19db4308 278 :group 'completion
36a3b01c 279 :link '(emacs-commentary-link :tag "Commentary" "iswitchb.el")
19db4308 280 :link '(url-link "http://www.anc.ed.ac.uk/~stephen/emacs/")
181688f2 281 :link '(emacs-library-link :tag "Lisp File" "iswitchb.el"))
36a3b01c
RS
282
283(defcustom iswitchb-case case-fold-search
8097dd15
GM
284 "*Non-nil if searching of buffer names should ignore case.
285If this is non-nil but the user input has any upper case letters, matching
286is temporarily case sensitive."
36a3b01c
RS
287 :type 'boolean
288 :group 'iswitchb)
962a4216 289
36a3b01c 290(defcustom iswitchb-buffer-ignore
962a4216 291 '("^ ")
6c56c80b
RS
292 "*List of regexps or functions matching buffer names to ignore.
293For example, traditional behavior is not to list buffers whose names begin
294with a space, for which the regexp is `^ '. See the source file for
36a3b01c
RS
295example functions that filter buffernames."
296 :type '(repeat regexp)
297 :group 'iswitchb)
298
c9403808
RS
299(defcustom iswitchb-cannot-complete-hook 'iswitchb-completion-help
300 "*Hook run when `iswitchb-complete' can't complete any more.
301The most useful values are `iswitchb-completion-help', which pops up a
302window with completion alternatives, or `iswitchb-next-match' or
303`iswitchb-prev-match', which cycle the buffer list."
304 :type 'hook
305 :group 'iswitchb)
306
962a4216 307;;; Examples for setting the value of iswitchb-buffer-ignore
6b0cc1b5 308;(defun iswitchb-ignore-c-mode (name)
962a4216
RS
309; "Ignore all c mode buffers -- example function for iswitchb."
310; (save-excursion
311; (set-buffer name)
312; (string-match "^C$" mode-name)))
313
6b0cc1b5 314;(setq iswitchb-buffer-ignore '("^ " iswitchb-ignore-c-mode))
962a4216
RS
315;(setq iswitchb-buffer-ignore '("^ " "\\.c$" "\\.h$"))
316
36a3b01c 317(defcustom iswitchb-default-method 'always-frame
6c56c80b 318 "*How to switch to new buffer when using `iswitchb-buffer'.
962a4216
RS
319Possible values:
320`samewindow' Show new buffer in same window
321`otherwindow' Show new buffer in another window (same frame)
888472e0 322`display' Display buffer in another window without switching to it
962a4216
RS
323`otherframe' Show new buffer in another frame
324`maybe-frame' If a buffer is visible in another frame, prompt to ask if you
325 you want to see the buffer in the same window of the current
326 frame or in the other frame.
c6e5b93f 327`always-frame' If a buffer is visible in another frame, raise that
36a3b01c 328 frame. Otherwise, visit the buffer in the same window."
19db4308 329 :type '(choice (const samewindow)
c6e5b93f
SE
330 (const otherwindow)
331 (const display)
19db4308 332 (const otherframe)
c6e5b93f
SE
333 (const maybe-frame)
334 (const always-frame))
36a3b01c 335 :group 'iswitchb)
962a4216 336
36a3b01c 337(defcustom iswitchb-regexp nil
6c56c80b 338 "*Non-nil means that `iswitchb' will do regexp matching.
6b0cc1b5 339Value can be toggled within `iswitchb' using `iswitchb-toggle-regexp'."
36a3b01c
RS
340 :type 'boolean
341 :group 'iswitchb)
342
36a3b01c 343(defcustom iswitchb-newbuffer t
962a4216 344 "*Non-nil means create new buffer if no buffer matches substring.
36a3b01c
RS
345See also `iswitchb-prompt-newbuffer'."
346 :type 'boolean
347 :group 'iswitchb)
962a4216 348
36a3b01c 349(defcustom iswitchb-prompt-newbuffer t
962a4216 350 "*Non-nil means prompt user to confirm before creating new buffer.
36a3b01c
RS
351See also `iswitchb-newbuffer'."
352 :type 'boolean
353 :group 'iswitchb)
354
36a3b01c 355(defcustom iswitchb-use-fonts t
6b0cc1b5 356 "*Non-nil means use font-lock fonts for showing first match."
36a3b01c
RS
357 :type 'boolean
358 :group 'iswitchb)
962a4216 359
f5bd1691
GM
360(defcustom iswitchb-use-frame-buffer-list nil
361 "*Non-nil means use the currently selected frame's buffer list."
362 :type 'boolean
363 :group 'iswitchb)
364
36a3b01c 365(defcustom iswitchb-make-buflist-hook nil
19db4308 366 "Hook to run when list of matching buffers is created."
36a3b01c
RS
367 :type 'hook
368 :group 'iswitchb)
369
962a4216
RS
370(defvar iswitchb-all-frames 'visible
371 "*Argument to pass to `walk-windows' when finding visible buffers.
372See documentation of `walk-windows' for useful values.")
373
6b0cc1b5 374(defcustom iswitchb-minibuffer-setup-hook nil
19db4308 375 "Iswitchb-specific customization of minibuffer setup.
962a4216 376
6c56c80b 377This hook is run during minibuffer setup iff `iswitchb' will be active.
962a4216 378It is intended for use in customizing iswitchb for interoperation
19db4308
DL
379with other packages."
380;;; For instance:
962a4216 381
19db4308
DL
382;;; \(add-hook 'iswitchb-minibuffer-setup-hook
383;;; \(function
384;;; \(lambda ()
385;;; \(make-local-variable 'resize-minibuffer-window-max-height)
386;;; \(setq resize-minibuffer-window-max-height 3))))
962a4216 387
19db4308
DL
388;;; will constrain rsz-mini to a maximum minibuffer height of 3 lines when
389;;; iswitchb is running. Copied from `icomplete-minibuffer-setup-hook'."
6b0cc1b5
SE
390 :type 'hook
391 :group 'iswitchb)
392
393;; Do we need the variable iswitchb-use-mycompletion?
394
6b0cc1b5
SE
395;;; Internal Variables
396
397(defvar iswitchb-method nil
19db4308 398 "Stores the method for viewing the selected buffer.
6b0cc1b5
SE
399Its value is one of `samewindow', `otherwindow', `display', `otherframe',
400`maybe-frame' or `always-frame'. See `iswitchb-default-method' for
401details of values.")
962a4216
RS
402
403(defvar iswitchb-eoinput 1
404 "Point where minibuffer input ends and completion info begins.
6c56c80b 405Copied from `icomplete-eoinput'.")
962a4216
RS
406(make-variable-buffer-local 'iswitchb-eoinput)
407
962a4216
RS
408(defvar iswitchb-buflist nil
409 "Stores the current list of buffers that will be searched through.
410The list is ordered, so that the most recent buffers come first,
411although by default, the buffers visible in the current frame are put
412at the end of the list. Created by `iswitchb-make-buflist'.")
413
414;; todo -- is this necessary?
415
416(defvar iswitchb-use-mycompletion nil
19db4308 417 "Non-nil means use `iswitchb-buffer' completion feedback.
6c56c80b
RS
418Should only be set to t by iswitchb functions, so that it doesn't
419interfere with other minibuffer usage.")
962a4216 420
19db4308 421(defvar iswitchb-change-word-sub nil
962a4216
RS
422 "Private variable used by `iswitchb-word-matching-substring'.")
423
962a4216
RS
424(defvar iswitchb-common-match-string nil
425 "Stores the string that is common to all matching buffers.")
426
962a4216
RS
427(defvar iswitchb-rescan nil
428 "Non-nil means we need to regenerate the list of matching buffers.")
429
430(defvar iswitchb-text nil
431 "Stores the users string as it is typed in.")
432
433(defvar iswitchb-matches nil
ccd2f997 434 "List of buffers currently matching `iswitchb-text'.")
962a4216 435
19db4308
DL
436(defvar iswitchb-mode-map
437 (let ((map (make-sparse-keymap)))
438 (set-keymap-parent map minibuffer-local-map)
439 (define-key map "?" 'iswitchb-completion-help)
440 (define-key map "\C-s" 'iswitchb-next-match)
441 (define-key map "\C-r" 'iswitchb-prev-match)
442 (define-key map "\t" 'iswitchb-complete)
443 (define-key map "\C-j" 'iswitchb-select-buffer-text)
444 (define-key map "\C-t" 'iswitchb-toggle-regexp)
445 (define-key map "\C-x\C-f" 'iswitchb-find-file)
446 (define-key map "\C-c" 'iswitchb-toggle-case)
447 (define-key map "\C-k" 'iswitchb-kill-buffer)
448 (define-key map "\C-m" 'iswitchb-exit-minibuffer)
449 map)
450 "Minibuffer keymap for `iswitchb-buffer'.")
451
452(defvar iswitchb-global-map
453 (let ((map (make-sparse-keymap)))
454 (substitute-key-definition 'switch-to-buffer ; normally C-x b
455 'iswitchb-buffer map global-map)
456 (substitute-key-definition 'switch-to-buffer-other-window ; C-x 4 b
457 'iswitchb-buffer-other-window map global-map)
458 (substitute-key-definition 'switch-to-buffer-other-frame ; C-x 5 b
459 'iswitchb-buffer-other-frame map global-map)
460 (substitute-key-definition 'display-buffer ; C-x 4 C-o
461 'iswitchb-display-buffer map global-map)
462 map)
463 "Global keymap for `iswtichb-mode'.")
464
465(defvar iswitchb-history nil
6c56c80b 466 "History of buffers selected using `iswitchb-buffer'.")
962a4216 467
19db4308
DL
468(defvar iswitchb-exit nil
469 "Flag to monitor how `iswitchb-buffer' exits.
6c56c80b
RS
470If equal to `takeprompt', we use the prompt as the buffer name to be
471selected.")
962a4216
RS
472
473(defvar iswitchb-buffer-ignore-orig nil
474 "Stores original value of `iswitchb-buffer-ignore'.")
475
476(defvar iswitchb-xemacs (string-match "XEmacs" (emacs-version))
477 "Non-nil if we are running XEmacs. Otherwise, assume we are running Emacs.")
478
6b0cc1b5
SE
479(defvar iswitchb-default nil
480 "Default buffer for iswitchb.")
962a4216 481
02e526ad
SE
482;; The following variables are needed to keep the byte compiler quiet.
483(defvar iswitchb-require-match nil
484 "Non-nil if matching buffer must be selected.")
485
486(defvar iswitchb-temp-buflist nil
487 "Stores a temporary version of the buffer list being created.")
488
489(defvar iswitchb-bufs-in-frame nil
490 "List of the buffers visible in the current frame.")
491
c7b89861
EZ
492(defvar iswitchb-minibuf-depth nil
493 "Value we expect to be returned by `minibuffer-depth' in the minibuffer.")
494
962a4216
RS
495;;; FUNCTIONS
496
19db4308 497;;; ISWITCHB KEYMAP
962a4216 498(defun iswitchb-define-mode-map ()
19db4308
DL
499 "Set up the keymap for `iswitchb-buffer'.
500This is obsolete. Use \\[iswitchb-mode] or customize the
501variable `iswitchb-mode'."
962a4216
RS
502 (interactive)
503 (let (map)
ccd2f997 504 ;; generated every time so that it can inherit new functions.
962a4216
RS
505 ;;(or iswitchb-mode-map
506
507 (setq map (copy-keymap minibuffer-local-map))
508 (define-key map "?" 'iswitchb-completion-help)
509 (define-key map "\C-s" 'iswitchb-next-match)
510 (define-key map "\C-r" 'iswitchb-prev-match)
511 (define-key map "\t" 'iswitchb-complete)
512 (define-key map "\C-j" 'iswitchb-select-buffer-text)
513 (define-key map "\C-t" 'iswitchb-toggle-regexp)
36a3b01c 514 (define-key map "\C-x\C-f" 'iswitchb-find-file)
962a4216
RS
515 ;;(define-key map "\C-a" 'iswitchb-toggle-ignore)
516 (define-key map "\C-c" 'iswitchb-toggle-case)
36a3b01c 517 (define-key map "\C-k" 'iswitchb-kill-buffer)
ccd2f997 518 (define-key map "\C-m" 'iswitchb-exit-minibuffer)
962a4216 519 (setq iswitchb-mode-map map)
181688f2 520 (run-hooks 'iswitchb-define-mode-map-hook)))
f1180544 521
962a4216
RS
522;;; MAIN FUNCTION
523(defun iswitchb ()
524 "Switch to buffer matching a substring.
525As you type in a string, all of the buffers matching the string are
526displayed. When you have found the buffer you want, it can then be
527selected. As you type, most keys have their normal keybindings,
528except for the following:
529\\<iswitchb-mode-map>
530
531RET Select the buffer at the front of the list of matches. If the
6c56c80b 532list is empty, possibly prompt to create new buffer.
962a4216
RS
533
534\\[iswitchb-select-buffer-text] Select the current prompt as the buffer.
535If no buffer is found, prompt for a new one.
536
537\\[iswitchb-next-match] Put the first element at the end of the list.
538\\[iswitchb-prev-match] Put the last element at the start of the list.
19db4308 539\\[iswitchb-complete] Complete a common suffix to the current string that
962a4216
RS
540matches all buffers. If there is only one match, select that buffer.
541If there is no common suffix, show a list of all matching buffers
542in a separate window.
ccd2f997 543\\[iswitchb-toggle-regexp] Toggle regexp searching.
962a4216 544\\[iswitchb-toggle-case] Toggle case-sensitive searching of buffer names.
36a3b01c 545\\[iswitchb-completion-help] Show list of matching buffers in separate window.
19db4308 546\\[iswitchb-find-file] Exit iswitchb and drop into `find-file'.
36a3b01c 547\\[iswitchb-kill-buffer] Kill buffer at head of buffer list."
962a4216
RS
548 ;;\\[iswitchb-toggle-ignore] Toggle ignoring certain buffers (see \
549 ;;`iswitchb-buffer-ignore')
f1180544 550
8ae3ef6e
SM
551 (let* ((prompt "iswitch ")
552 (buf (iswitchb-read-buffer prompt)))
ccd2f997 553
ccd2f997
KH
554 ;;(message "chosen text %s" iswitchb-final-text)
555 ;; Choose the buffer name: either the text typed in, or the head
556 ;; of the list of matches
557
558 (cond ( (eq iswitchb-exit 'findfile)
559 (call-interactively 'find-file))
560
561 (t
562 ;; View the buffer
c6e5b93f 563 ;;(message "go to buf %s" buf)
ccd2f997
KH
564 ;; Check buf is non-nil.
565 (if buf
566 (if (get-buffer buf)
567 ;; buffer exists, so view it and then exit
568 (iswitchb-visit-buffer buf)
569 ;; else buffer doesn't exist
570 (iswitchb-possible-new-buffer buf)))
181688f2 571 ))))
ccd2f997 572
abc8b974 573;;;###autoload
ccd2f997
KH
574(defun iswitchb-read-buffer (prompt &optional default require-match)
575 "Replacement for the built-in `read-buffer'.
19db4308 576Return the name of a buffer selected.
ccd2f997
KH
577PROMPT is the prompt to give to the user. DEFAULT if given is the default
578buffer to be selected, which will go to the front of the list.
579If REQUIRE-MATCH is non-nil, an existing-buffer must be selected."
962a4216
RS
580 (let
581 (
962a4216
RS
582 buf-sel
583 iswitchb-final-text
962a4216 584 (icomplete-mode nil) ;; prevent icomplete starting up
962a4216
RS
585 ;; can only use fonts if they have been bound.
586 (iswitchb-use-fonts (and iswitchb-use-fonts
587 (boundp 'font-lock-comment-face)
ccd2f997
KH
588 (boundp 'font-lock-function-name-face))))
589
962a4216 590 (iswitchb-define-mode-map)
962a4216
RS
591 (setq iswitchb-exit nil)
592 (setq iswitchb-rescan t)
593 (setq iswitchb-text "")
6b0cc1b5
SE
594 (setq iswitchb-default
595 (if (bufferp default)
596 (buffer-name default)
597 default))
598 (iswitchb-make-buflist iswitchb-default)
36a3b01c 599 (iswitchb-set-matches)
19db4308 600 (let
ccd2f997
KH
601 ((minibuffer-local-completion-map iswitchb-mode-map)
602 (iswitchb-prepost-hooks t)
c7b89861
EZ
603 ;; Record the minibuffer depth that we expect to find once
604 ;; the minibuffer is set up and iswitchb-entryfn-p is called.
605 (iswitchb-minibuf-depth (1+ (minibuffer-depth)))
181688f2 606 (iswitchb-require-match require-match))
36a3b01c 607 ;; prompt the user for the buffer name
19db4308 608 (setq iswitchb-final-text (completing-read
ccd2f997 609 prompt ;the prompt
660e161f 610 '(("dummy" . 1)) ;table
ccd2f997
KH
611 nil ;predicate
612 nil ;require-match [handled elsewhere]
613 nil ;initial-contents
614 'iswitchb-history)))
8ae3ef6e
SM
615 (if (get-buffer iswitchb-final-text)
616 ;; This happens for example if the buffer was chosen with the mouse.
617 (setq iswitchb-matches (list iswitchb-final-text)))
618
ccd2f997
KH
619 ;; Handling the require-match must be done in a better way.
620 (if (and require-match (not (iswitchb-existing-buffer-p)))
19db4308 621 (error "Must specify valid buffer"))
ccd2f997 622
19db4308 623 (if (or
ccd2f997
KH
624 (eq iswitchb-exit 'takeprompt)
625 (null iswitchb-matches))
626 (setq buf-sel iswitchb-final-text)
627 ;; else take head of list
628 (setq buf-sel (car iswitchb-matches)))
f1180544 629
ccd2f997 630 ;; Or possibly choose the default buffer
19db4308
DL
631 (if (equal iswitchb-final-text "")
632 (setq buf-sel
ccd2f997 633 (car iswitchb-matches)))
36a3b01c 634
ccd2f997 635 buf-sel))
36a3b01c 636
ccd2f997
KH
637(defun iswitchb-existing-buffer-p ()
638 "Return non-nil if there is a matching buffer."
639 (not (null iswitchb-matches)))
962a4216
RS
640
641;;; COMPLETION CODE
642
643(defun iswitchb-set-common-completion ()
6c56c80b
RS
644 "Find common completion of `iswitchb-text' in `iswitchb-matches'.
645The result is stored in `iswitchb-common-match-string'."
962a4216
RS
646
647 (let* (val)
648 (setq iswitchb-common-match-string nil)
649 (if (and iswitchb-matches
6b0cc1b5 650 (not iswitchb-regexp) ;; testing
962a4216
RS
651 (stringp iswitchb-text)
652 (> (length iswitchb-text) 0))
653 (if (setq val (iswitchb-find-common-substring
654 iswitchb-matches iswitchb-text))
655 (setq iswitchb-common-match-string val)))
181688f2 656 val))
962a4216
RS
657
658(defun iswitchb-complete ()
659 "Try and complete the current pattern amongst the buffer names."
660 (interactive)
661 (let (res)
662 (cond ((not iswitchb-matches)
c9403808 663 (run-hooks 'iswitchb-cannot-complete-hook))
f1180544 664
ccd2f997 665 ((= 1 (length iswitchb-matches))
962a4216
RS
666 ;; only one choice, so select it.
667 (exit-minibuffer))
f1180544 668
962a4216
RS
669 (t
670 ;; else there could be some completions
6b0cc1b5 671 (setq res iswitchb-common-match-string)
962a4216 672 (if (and (not (memq res '(t nil)))
36a3b01c 673 (not (equal res iswitchb-text)))
ccd2f997 674 ;; found something to complete, so put it in the minibuffer.
962a4216
RS
675 (progn
676 (setq iswitchb-rescan nil)
53811b42 677 (delete-region (minibuffer-prompt-end) (point))
962a4216
RS
678 (insert res))
679 ;; else nothing to complete
c9403808 680 (run-hooks 'iswitchb-cannot-complete-hook)
181688f2 681 )))))
962a4216
RS
682
683;;; TOGGLE FUNCTIONS
684
685(defun iswitchb-toggle-case ()
19db4308 686 "Toggle the value of variable `iswitchb-case'."
962a4216
RS
687 (interactive)
688 (setq iswitchb-case (not iswitchb-case))
689 ;; ask for list to be regenerated.
181688f2 690 (setq iswitchb-rescan t))
962a4216
RS
691
692(defun iswitchb-toggle-regexp ()
693 "Toggle the value of `iswitchb-regexp'."
694 (interactive)
695 (setq iswitchb-regexp (not iswitchb-regexp))
696 ;; ask for list to be regenerated.
181688f2 697 (setq iswitchb-rescan t))
962a4216
RS
698
699(defun iswitchb-toggle-ignore ()
700 "Toggle ignoring buffers specified with `iswitchb-buffer-ignore'."
701 (interactive)
702 (if iswitchb-buffer-ignore
703 (progn
704 (setq iswitchb-buffer-ignore-orig iswitchb-buffer-ignore)
181688f2 705 (setq iswitchb-buffer-ignore nil))
962a4216 706 ;; else
181688f2 707 (setq iswitchb-buffer-ignore iswitchb-buffer-ignore-orig))
6b0cc1b5 708 (iswitchb-make-buflist iswitchb-default)
962a4216 709 ;; ask for list to be regenerated.
181688f2 710 (setq iswitchb-rescan t))
962a4216 711
ccd2f997
KH
712(defun iswitchb-exit-minibuffer ()
713 "Exit minibuffer, but make sure we have a match if one is needed."
714 (interactive)
715 (if (or (not iswitchb-require-match)
716 (iswitchb-existing-buffer-p))
181688f2 717 (throw 'exit nil)))
962a4216
RS
718
719(defun iswitchb-select-buffer-text ()
6c56c80b
RS
720 "Select the buffer named by the prompt.
721If no buffer exactly matching the prompt exists, maybe create a new one."
962a4216
RS
722 (interactive)
723 (setq iswitchb-exit 'takeprompt)
724 (exit-minibuffer))
725
36a3b01c 726(defun iswitchb-find-file ()
19db4308 727 "Drop into `find-file' from buffer switching."
36a3b01c
RS
728 (interactive)
729 (setq iswitchb-exit 'findfile)
730 (exit-minibuffer))
731
19db4308 732(defun iswitchb-next-match ()
962a4216
RS
733 "Put first element of `iswitchb-matches' at the end of the list."
734 (interactive)
36a3b01c
RS
735 (let ((next (cadr iswitchb-matches)))
736 (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist next))
181688f2 737 (setq iswitchb-rescan t)))
962a4216 738
19db4308 739(defun iswitchb-prev-match ()
962a4216
RS
740 "Put last element of `iswitchb-matches' at the front of the list."
741 (interactive)
36a3b01c
RS
742 (let ((prev (car (last iswitchb-matches))))
743 (setq iswitchb-buflist (iswitchb-chop iswitchb-buflist prev))
181688f2 744 (setq iswitchb-rescan t)))
36a3b01c
RS
745
746(defun iswitchb-chop (list elem)
747 "Remove all elements before ELEM and put them at the end of LIST."
748 (let ((ret nil)
749 (next nil)
750 (sofar nil))
751 (while (not ret)
752 (setq next (car list))
753 (if (equal next elem)
754 (setq ret (append list (nreverse sofar)))
755 ;; else
756 (progn
757 (setq list (cdr list))
758 (setq sofar (cons next sofar)))))
759 ret))
962a4216 760
962a4216
RS
761;;; CREATE LIST OF ALL CURRENT BUFFERS
762
ccd2f997 763(defun iswitchb-make-buflist (default)
6c56c80b 764 "Set `iswitchb-buflist' to the current list of buffers.
36a3b01c 765Currently visible buffers are put at the end of the list.
19db4308 766The hook `iswitchb-make-buflist-hook' is run after the list has been
36a3b01c 767created to allow the user to further modify the order of the buffer names
ccd2f997
KH
768in this list. If DEFAULT is non-nil, and corresponds to an existing buffer,
769it is put to the start of the list."
19db4308 770 (setq iswitchb-buflist
36a3b01c 771 (let* ((iswitchb-current-buffers (iswitchb-get-buffers-in-frames))
ceba0dac
GM
772 (iswitchb-temp-buflist
773 (delq nil
774 (mapcar
775 (lambda (x)
776 (let ((b-name (buffer-name x)))
777 (if (not
778 (or
779 (iswitchb-ignore-buffername-p b-name)
780 (memq b-name iswitchb-current-buffers)))
781 b-name)))
782 (buffer-list (and iswitchb-use-frame-buffer-list
783 (selected-frame)))))))
784 (setq iswitchb-temp-buflist
785 (nconc iswitchb-temp-buflist iswitchb-current-buffers))
962a4216 786 (run-hooks 'iswitchb-make-buflist-hook)
ceba0dac 787 ;; Should this be after the hooks, or should the hooks be the
ccd2f997
KH
788 ;; final thing to be run?
789 (if default
790 (progn
19db4308 791 (setq iswitchb-temp-buflist
02e526ad 792 (delete default iswitchb-temp-buflist))
19db4308 793 (setq iswitchb-temp-buflist
02e526ad
SE
794 (cons default iswitchb-temp-buflist))))
795 iswitchb-temp-buflist)))
962a4216 796
36a3b01c 797(defun iswitchb-to-end (lst)
02e526ad 798 "Move the elements from LST to the end of `iswitchb-temp-buflist'."
19db4308
DL
799 (mapcar
800 (lambda (elem)
02e526ad 801 (setq iswitchb-temp-buflist (delq elem iswitchb-temp-buflist)))
36a3b01c 802 lst)
ceba0dac 803 (setq iswitchb-temp-buflist (nconc iswitchb-temp-buflist lst)))
962a4216 804
962a4216 805(defun iswitchb-get-buffers-in-frames (&optional current)
962a4216 806 "Return the list of buffers that are visible in the current frame.
19db4308 807If optional argument CURRENT is given, restrict searching to the
962a4216
RS
808current frame, rather than all frames, regardless of value of
809`iswitchb-all-frames'."
962a4216 810 (let ((iswitchb-bufs-in-frame nil))
962a4216 811 (walk-windows 'iswitchb-get-bufname nil
19db4308 812 (if current
962a4216
RS
813 nil
814 iswitchb-all-frames))
815 iswitchb-bufs-in-frame))
816
962a4216
RS
817(defun iswitchb-get-bufname (win)
818 "Used by `iswitchb-get-buffers-in-frames' to walk through all windows."
ae5ac7d0
RS
819 (let ((buf (buffer-name (window-buffer win))))
820 (if (not (member buf iswitchb-bufs-in-frame))
821 ;; Only add buf if it is not already in list.
822 ;; This prevents same buf in two different windows being
823 ;; put into the list twice.
824 (setq iswitchb-bufs-in-frame
825 (cons buf iswitchb-bufs-in-frame)))))
962a4216 826
962a4216
RS
827;;; FIND MATCHING BUFFERS
828
829(defun iswitchb-set-matches ()
830 "Set `iswitchb-matches' to the list of buffers matching prompt."
962a4216
RS
831 (if iswitchb-rescan
832 (setq iswitchb-matches
181688f2 833 (let* ((buflist iswitchb-buflist))
36a3b01c 834 (iswitchb-get-matched-buffers iswitchb-text iswitchb-regexp
6b0cc1b5 835 buflist)))))
36a3b01c
RS
836
837(defun iswitchb-get-matched-buffers (regexp
838 &optional string-format buffer-list)
6b0cc1b5
SE
839 "Return buffers matching REGEXP.
840If STRING-FORMAT is nil, consider REGEXP as just a string.
6c56c80b 841BUFFER-LIST can be list of buffers or list of strings."
8097dd15 842 (let* ((case-fold-search (iswitchb-case))
962a4216
RS
843 ;; need reverse since we are building up list backwards
844 (list (reverse buffer-list))
6b0cc1b5 845 (do-string (stringp (car list)))
962a4216 846 name
181688f2 847 ret)
962a4216 848 (mapcar
36a3b01c 849 (lambda (x)
f1180544 850
36a3b01c
RS
851 (if do-string
852 (setq name x) ;We already have the name
853 (setq name (buffer-name x)))
f1180544 854
36a3b01c
RS
855 (cond
856 ((and (or (and string-format (string-match regexp name))
857 (and (null string-format)
858 (string-match (regexp-quote regexp) name)))
f1180544 859
181688f2 860 (not (iswitchb-ignore-buffername-p name)))
36a3b01c
RS
861 (setq ret (cons name ret))
862 )))
962a4216 863 list)
181688f2 864 ret))
962a4216
RS
865
866(defun iswitchb-ignore-buffername-p (bufname)
867 "Return t if the buffer BUFNAME should be ignored."
868 (let ((data (match-data))
869 (re-list iswitchb-buffer-ignore)
870 ignorep
181688f2 871 nextstr)
962a4216
RS
872 (while re-list
873 (setq nextstr (car re-list))
874 (cond
875 ((stringp nextstr)
876 (if (string-match nextstr bufname)
877 (progn
878 (setq ignorep t)
879 (setq re-list nil))))
880 ((fboundp nextstr)
881 (if (funcall nextstr bufname)
882 (progn
883 (setq ignorep t)
181688f2 884 (setq re-list nil)))))
962a4216 885 (setq re-list (cdr re-list)))
25c80f5c 886 (set-match-data data)
962a4216
RS
887
888 ;; return the result
181688f2 889 ignorep))
962a4216 890
962a4216
RS
891(defun iswitchb-word-matching-substring (word)
892 "Return part of WORD before 1st match to `iswitchb-change-word-sub'.
893If `iswitchb-change-word-sub' cannot be found in WORD, return nil."
8097dd15 894 (let ((case-fold-search (iswitchb-case)))
962a4216
RS
895 (let ((m (string-match iswitchb-change-word-sub word)))
896 (if m
897 (substring word m)
898 ;; else no match
899 nil))))
900
962a4216
RS
901(defun iswitchb-find-common-substring (lis subs)
902 "Return common string following SUBS in each element of LIS."
903 (let (res
904 alist
181688f2 905 iswitchb-change-word-sub)
962a4216
RS
906 (setq iswitchb-change-word-sub
907 (if iswitchb-regexp
908 subs
909 (regexp-quote subs)))
910 (setq res (mapcar 'iswitchb-word-matching-substring lis))
ccd2f997 911 (setq res (delq nil res)) ;; remove any nil elements (shouldn't happen)
962a4216
RS
912 (setq alist (mapcar 'iswitchb-makealist res)) ;; could use an OBARRAY
913
914 ;; try-completion returns t if there is an exact match.
8097dd15 915 (let ((completion-ignore-case (iswitchb-case)))
962a4216 916
181688f2 917 (try-completion subs alist))))
962a4216
RS
918
919(defun iswitchb-makealist (res)
920 "Return dotted pair (RES . 1)."
921 (cons res 1))
922
923;; from Wayne Mesard <wmesard@esd.sgi.com>
924(defun iswitchb-rotate-list (lis)
19db4308 925 "Destructively remove the last element from LIS.
962a4216
RS
926Return the modified list with the last element prepended to it."
927 (if (<= (length lis) 1)
928 lis
929 (let ((las lis)
930 (prev lis))
931 (while (consp (cdr las))
932 (setq prev las
933 las (cdr las)))
934 (setcdr prev nil)
181688f2 935 (cons (car las) lis))))
962a4216
RS
936
937(defun iswitchb-completion-help ()
8ae3ef6e 938 "Show possible completions in a *Completions* buffer."
962a4216 939 ;; we could allow this buffer to be used to select match, but I think
36a3b01c 940 ;; choose-completion-string will need redefining, so it just inserts
19db4308 941 ;; choice with out any previous input.
962a4216 942 (interactive)
36a3b01c 943 (setq iswitchb-rescan nil)
8ae3ef6e
SM
944 (let ((buf (current-buffer))
945 (temp-buf "*Completions*")
946 (win))
ccd2f997 947
8ae3ef6e 948 (if (eq last-command this-command)
ccd2f997
KH
949 ;; scroll buffer
950 (progn
951 (set-buffer temp-buf)
952 (setq win (get-buffer-window temp-buf))
953 (if (pos-visible-in-window-p (point-max) win)
954 (set-window-start win (point-min))
955 (scroll-other-window))
181688f2 956 (set-buffer buf))
f1180544 957
ccd2f997 958 (with-output-to-temp-buffer temp-buf
19db4308 959 (if iswitchb-xemacs
f1180544 960
ccd2f997
KH
961 ;; XEmacs extents are put on by default, doesn't seem to be
962 ;; any way of switching them off.
963 (display-completion-list (if iswitchb-matches
964 iswitchb-matches
965 iswitchb-buflist)
966 :help-string "iswitchb "
19db4308
DL
967 :activate-callback
968 (lambda (x y z)
969 (message "doesn't work yet, sorry!")))
ccd2f997 970 ;; else running Emacs
19db4308
DL
971 (with-current-buffer standard-output
972 (fundamental-mode))
ccd2f997 973 (display-completion-list (if iswitchb-matches
19db4308 974 iswitchb-matches
ccd2f997
KH
975 iswitchb-buflist))
976 )))))
977
36a3b01c
RS
978;;; KILL CURRENT BUFFER
979
980(defun iswitchb-kill-buffer ()
ccd2f997 981 "Kill the buffer at the head of `iswitchb-matches'."
36a3b01c
RS
982 (interactive)
983 (let ( (enable-recursive-minibuffers t)
984 buf)
985
986 (setq buf (car iswitchb-matches))
987 ;; check to see if buf is non-nil.
988 (if buf
989 (progn
990 (kill-buffer buf)
991
992 ;; Check if buffer exists. XEmacs gnuserv.el makes alias
993 ;; for kill-buffer which does not return t if buffer is
994 ;; killed, so we can't rely on kill-buffer return value.
995 (if (get-buffer buf)
996 ;; buffer couldn't be killed.
19db4308 997 (setq iswitchb-rescan t)
36a3b01c
RS
998 ;; else buffer was killed so remove name from list.
999 (setq iswitchb-buflist (delq buf iswitchb-buflist)))))))
1000
962a4216
RS
1001;;; VISIT CHOSEN BUFFER
1002(defun iswitchb-visit-buffer (buffer)
1003 "Visit buffer named BUFFER according to `iswitchb-method'."
1004 (let* (win newframe)
1005 (cond
1006 ((eq iswitchb-method 'samewindow)
1007 (switch-to-buffer buffer))
1008
1009 ((memq iswitchb-method '(always-frame maybe-frame))
1010 (cond
1011 ((and (setq win (iswitchb-window-buffer-p buffer))
1012 (or (eq iswitchb-method 'always-frame)
1013 (y-or-n-p "Jump to frame? ")))
1014 (setq newframe (window-frame win))
4d8ae757
RS
1015 (if (not iswitchb-xemacs)
1016 (select-frame-set-input-focus newframe)
1017 (raise-frame newframe)
1018 (select-frame newframe)
1019 )
1020 (select-window win))
962a4216
RS
1021 (t
1022 ;; No buffer in other frames...
1023 (switch-to-buffer buffer)
1024 )))
1025
962a4216
RS
1026 ((eq iswitchb-method 'otherwindow)
1027 (switch-to-buffer-other-window buffer))
1028
888472e0
RS
1029 ((eq iswitchb-method 'display)
1030 (display-buffer buffer))
1031
962a4216
RS
1032 ((eq iswitchb-method 'otherframe)
1033 (progn
1034 (switch-to-buffer-other-frame buffer)
1035 (if (not iswitchb-xemacs)
4d8ae757 1036 (select-frame-set-input-focus (selected-frame)))
181688f2 1037 )))))
962a4216
RS
1038
1039(defun iswitchb-possible-new-buffer (buf)
1040 "Possibly create and visit a new buffer called BUF."
1041
1042 (let ((newbufcreated))
1043 (if (and iswitchb-newbuffer
1044 (or
1045 (not iswitchb-prompt-newbuffer)
f1180544 1046
962a4216
RS
1047 (and iswitchb-prompt-newbuffer
1048 (y-or-n-p
1049 (format
1050 "No buffer matching `%s', create one? "
1051 buf)))))
1052 ;; then create a new buffer
1053 (progn
1054 (setq newbufcreated (get-buffer-create buf))
1055 (if (fboundp 'set-buffer-major-mode)
1056 (set-buffer-major-mode newbufcreated))
1057 (iswitchb-visit-buffer newbufcreated))
1058 ;; else wont create new buffer
181688f2 1059 (message (format "no buffer matching `%s'" buf)))))
962a4216
RS
1060
1061(defun iswitchb-window-buffer-p (buffer)
6c56c80b
RS
1062 "Return window pointer if BUFFER is visible in another frame.
1063If BUFFER is visible in the current frame, return nil."
962a4216 1064 (interactive)
962a4216
RS
1065 (let ((blist (iswitchb-get-buffers-in-frames 'current)))
1066 ;;If the buffer is visible in current frame, return nil
1067 (if (memq buffer blist)
1068 nil
ccd2f997
KH
1069 ;; maybe in other frame or icon
1070 (get-buffer-window buffer 0) ; better than 'visible
962a4216
RS
1071 )))
1072
6c56c80b 1073;;;###autoload
962a4216 1074(defun iswitchb-default-keybindings ()
6c56c80b 1075 "Set up default keybindings for `iswitchb-buffer'.
ee5897a4 1076Call this function to override the normal bindings. This function also
19db4308
DL
1077adds a hook to the minibuffer.
1078
1079Obsolescent. Use `iswitchb-mode'."
962a4216 1080 (interactive)
ee5897a4 1081 (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)
322524b2
SE
1082 (global-set-key "\C-xb" 'iswitchb-buffer)
1083 (global-set-key "\C-x4b" 'iswitchb-buffer-other-window)
1084 (global-set-key "\C-x4\C-o" 'iswitchb-display-buffer)
1085 (global-set-key "\C-x5b" 'iswitchb-buffer-other-frame))
962a4216 1086
962a4216
RS
1087;;;###autoload
1088(defun iswitchb-buffer ()
1089 "Switch to another buffer.
1090
1091The buffer name is selected interactively by typing a substring. The
1092buffer is displayed according to `iswitchb-default-method' -- the
1093default is to show it in the same window, unless it is already visible
6c56c80b
RS
1094in another frame.
1095For details of keybindings, do `\\[describe-function] iswitchb'."
962a4216
RS
1096 (interactive)
1097 (setq iswitchb-method iswitchb-default-method)
ccd2f997 1098 (iswitchb))
962a4216 1099
962a4216
RS
1100;;;###autoload
1101(defun iswitchb-buffer-other-window ()
1102 "Switch to another buffer and show it in another window.
1103The buffer name is selected interactively by typing a substring.
6c56c80b 1104For details of keybindings, do `\\[describe-function] iswitchb'."
962a4216
RS
1105 (interactive)
1106 (setq iswitchb-method 'otherwindow)
ccd2f997 1107 (iswitchb))
962a4216 1108
888472e0
RS
1109;;;###autoload
1110(defun iswitchb-display-buffer ()
1111 "Display a buffer in another window but don't select it.
1112The buffer name is selected interactively by typing a substring.
1113For details of keybindings, do `\\[describe-function] iswitchb'."
1114 (interactive)
1115 (setq iswitchb-method 'display)
ccd2f997 1116 (iswitchb))
888472e0 1117
962a4216
RS
1118;;;###autoload
1119(defun iswitchb-buffer-other-frame ()
1120 "Switch to another buffer and show it in another frame.
1121The buffer name is selected interactively by typing a substring.
6c56c80b 1122For details of keybindings, do `\\[describe-function] iswitchb'."
962a4216
RS
1123 (interactive)
1124 (setq iswitchb-method 'otherframe)
962a4216
RS
1125 (iswitchb))
1126
36a3b01c 1127;;; XEmacs hack for showing default buffer
962a4216
RS
1128
1129;; The first time we enter the minibuffer, Emacs puts up the default
ccd2f997 1130;; buffer to switch to, but XEmacs doesn't -- presumably there is a
36a3b01c
RS
1131;; subtle difference in the two versions of post-command-hook. The
1132;; default is shown for both whenever we delete all of our text
1133;; though, indicating its just a problem the first time we enter the
1134;; function. To solve this, we use another entry hook for emacs to
1135;; show the default the first time we enter the minibuffer.
962a4216 1136
6b0cc1b5 1137(defun iswitchb-init-XEmacs-trick ()
6c56c80b
RS
1138 "Display default buffer when first entering minibuffer.
1139This is a hack for XEmacs, and should really be handled by `iswitchb-exhibit'."
962a4216
RS
1140 (if (iswitchb-entryfn-p)
1141 (progn
36a3b01c 1142 (iswitchb-exhibit)
962a4216
RS
1143 (goto-char (point-min)))))
1144
36a3b01c 1145;; add this hook for XEmacs only.
962a4216 1146(if iswitchb-xemacs
19db4308 1147 (add-hook 'iswitchb-minibuffer-setup-hook
6b0cc1b5 1148 'iswitchb-init-XEmacs-trick))
962a4216 1149
36a3b01c 1150;;; XEmacs / backspace key
ccd2f997 1151;; For some reason, if the backspace key is pressed in XEmacs, the
962a4216 1152;; line gets confused, so I've added a simple key definition to make
19db4308 1153;; backspace act like the normal delete key.
962a4216
RS
1154
1155(defun iswitchb-xemacs-backspacekey ()
1156 "Bind backspace to `backward-delete-char'."
1157 (define-key iswitchb-mode-map '[backspace] 'backward-delete-char)
181688f2 1158 (define-key iswitchb-mode-map '[(meta backspace)] 'backward-kill-word))
962a4216
RS
1159
1160(if iswitchb-xemacs
19db4308 1161 (add-hook 'iswitchb-define-mode-map-hook
962a4216
RS
1162 'iswitchb-xemacs-backspacekey))
1163
962a4216
RS
1164;;; ICOMPLETE TYPE CODE
1165
1166(defun iswitchb-exhibit ()
6c56c80b 1167 "Find matching buffers and display a list in the minibuffer.
962a4216
RS
1168Copied from `icomplete-exhibit' with two changes:
11691. It prints a default buffer name when there is no text yet entered.
11702. It calls my completion routine rather than the standard completion."
962a4216 1171 (if iswitchb-use-mycompletion
600f9d03 1172 (let ((contents (buffer-substring (minibuffer-prompt-end) (point-max)))
962a4216
RS
1173 (buffer-undo-list t))
1174 (save-excursion
1175 (goto-char (point-max))
1176 ; Register the end of input, so we
1177 ; know where the extra stuff
1178 ; (match-status info) begins:
1179 (if (not (boundp 'iswitchb-eoinput))
1180 ;; In case it got wiped out by major mode business:
1181 (make-local-variable 'iswitchb-eoinput))
1182 (setq iswitchb-eoinput (point))
1183 ;; Update the list of matches
1184 (setq iswitchb-text contents)
1185 (iswitchb-set-matches)
1186 (setq iswitchb-rescan t)
1187 (iswitchb-set-common-completion)
1188
1189 ;; Insert the match-status information:
f1180544 1190 (insert (iswitchb-completions
34d16326
PJ
1191 contents
1192 minibuffer-completion-table
1193 minibuffer-completion-predicate
1194 (not minibuffer-completion-confirm)))))))
26119624
GM
1195
1196(defun iswitchb-completions (name candidates predicate require-match)
962a4216
RS
1197 "Return the string that is displayed after the user's text.
1198Modified from `icomplete-completions'."
f1180544 1199
962a4216
RS
1200 (let ((comps iswitchb-matches)
1201 ; "-determined" - only one candidate
1202 (open-bracket-determined (if require-match "(" "["))
1203 (close-bracket-determined (if require-match ")" "]"))
1204 ;"-prospects" - more than one candidate
1205 (open-bracket-prospects "{")
1206 (close-bracket-prospects "}")
181688f2 1207 first)
962a4216
RS
1208
1209 (if (and iswitchb-use-fonts comps)
1210 (progn
1211 (setq first (car comps))
1212 (setq first (format "%s" first))
1213 (put-text-property 0 (length first) 'face
19db4308 1214 (if (= (length comps) 1)
962a4216
RS
1215 'font-lock-comment-face
1216 'font-lock-function-name-face)
19db4308 1217 first)
181688f2 1218 (setq comps (cons first (cdr comps)))))
962a4216
RS
1219
1220 (cond ((null comps) (format " %sNo match%s"
1221 open-bracket-determined
1222 close-bracket-determined))
1223
1224 ((null (cdr comps)) ;one match
1225 (concat (if (and (> (length (car comps))
1226 (length name)))
1227 (concat open-bracket-determined
19db4308 1228 ;; when there is one match, show the
962a4216
RS
1229 ;; matching buffer name in full
1230 (car comps)
1231 close-bracket-determined)
1232 "")
181688f2 1233 (if (not iswitchb-use-fonts) " [Matched]")))
962a4216
RS
1234 (t ;multiple matches
1235 (let* (
1236 ;;(most (try-completion name candidates predicate))
1237 (most nil)
1238 (most-len (length most))
1239 most-is-exact
1240 first
1241 (alternatives
1242 (apply
1243 (function concat)
1244 (cdr (apply
1245 (function nconc)
1246 (mapcar '(lambda (com)
1247 (if (= (length com) most-len)
1248 ;; Most is one exact match,
1249 ;; note that and leave out
1250 ;; for later indication:
1251 (progn
1252 (setq most-is-exact t)
1253 ())
1254 (list ","
1255 (substring com
1256 most-len))))
1257 comps))))))
1258
1259 (concat
1260
1261 ;; put in common completion item -- what you get by
1262 ;; pressing tab
4e141ed7
SE
1263 (if (and (stringp iswitchb-common-match-string)
1264 (> (length iswitchb-common-match-string) (length name)))
962a4216 1265 (concat open-bracket-determined
19db4308 1266 (substring iswitchb-common-match-string
962a4216 1267 (length name))
181688f2 1268 close-bracket-determined))
962a4216
RS
1269 ;; end of partial matches...
1270
1271 ;; think this bit can be ignored.
1272 (and (> most-len (length name))
1273 (concat open-bracket-determined
1274 (substring most (length name))
1275 close-bracket-determined))
f1180544 1276
962a4216
RS
1277 ;; list all alternatives
1278 open-bracket-prospects
1279 (if most-is-exact
1280 (concat "," alternatives)
1281 alternatives)
181688f2 1282 close-bracket-prospects))))))
962a4216
RS
1283
1284(defun iswitchb-minibuffer-setup ()
6c56c80b
RS
1285 "Set up minibuffer for `iswitchb-buffer'.
1286Copied from `icomplete-minibuffer-setup-hook'."
8ae3ef6e
SM
1287 (when (iswitchb-entryfn-p)
1288 (set (make-local-variable 'iswitchb-use-mycompletion) t)
1289 (add-hook 'pre-command-hook 'iswitchb-pre-command nil t)
1290 (add-hook 'post-command-hook 'iswitchb-post-command nil t)
1291 (run-hooks 'iswitchb-minibuffer-setup-hook)))
962a4216
RS
1292
1293(defun iswitchb-pre-command ()
6c56c80b 1294 "Run before command in `iswitchb-buffer'."
962a4216
RS
1295 (iswitchb-tidy))
1296
962a4216 1297(defun iswitchb-post-command ()
6c56c80b 1298 "Run after command in `iswitchb-buffer'."
181688f2 1299 (iswitchb-exhibit))
962a4216
RS
1300
1301(defun iswitchb-tidy ()
1302 "Remove completions display, if any, prior to new user input.
1303Copied from `icomplete-tidy'."
1304
1305 (if (and (boundp 'iswitchb-eoinput)
1306 iswitchb-eoinput)
f1180544 1307
962a4216
RS
1308 (if (> iswitchb-eoinput (point-max))
1309 ;; Oops, got rug pulled out from under us - reinit:
1310 (setq iswitchb-eoinput (point-max))
1311 (let ((buffer-undo-list buffer-undo-list )) ; prevent entry
1312 (delete-region iswitchb-eoinput (point-max))))
f1180544 1313
962a4216
RS
1314 ;; Reestablish the local variable 'cause minibuffer-setup is weird:
1315 (make-local-variable 'iswitchb-eoinput)
1316 (setq iswitchb-eoinput 1)))
1317
962a4216 1318(defun iswitchb-entryfn-p ()
26119624 1319 "Return non-nil if we are using `iswitchb-buffer'."
c7b89861 1320 (eq iswitchb-minibuf-depth (minibuffer-depth)))
ccd2f997 1321
962a4216 1322(defun iswitchb-summaries-to-end ()
6c56c80b
RS
1323 "Move the summaries to the end of the list.
1324This is an example function which can be hooked on to
1325`iswitchb-make-buflist-hook'. Any buffer matching the regexps
1326`Summary' or `output\*$'are put to the end of the list."
19db4308
DL
1327 (let ((summaries (delq nil
1328 (mapcar
1329 (lambda (x)
1330 (if (string-match "Summary\\|output\\*$" x)
1331 x))
1332 iswitchb-temp-buflist))))
36a3b01c 1333 (iswitchb-to-end summaries)))
962a4216 1334
8097dd15
GM
1335(defun iswitchb-case ()
1336 "Return non-nil iff we should ignore case when matching.
1337See the variable `iswitchb-case' for details."
1338 (if iswitchb-case
1339 (if iswitchb-xemacs
1340 (isearch-no-upper-case-p iswitchb-text)
1341 (isearch-no-upper-case-p iswitchb-text t))))
1342
19db4308 1343;;;###autoload
8ae3ef6e 1344(define-minor-mode iswitchb-mode
19db4308
DL
1345 "Toggle Iswitchb global minor mode.
1346With arg, turn Iswitchb mode on if and only iff ARG is positive.
1347This mode enables switching between buffers using substrings. See
1348`iswitchb' for details."
8ae3ef6e 1349 nil nil iswitchb-global-map :global t :group 'iswitchb
19db4308
DL
1350 (if iswitchb-mode
1351 (add-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)
8ae3ef6e 1352 (remove-hook 'minibuffer-setup-hook 'iswitchb-minibuffer-setup)))
19db4308 1353
962a4216
RS
1354(provide 'iswitchb)
1355
6c56c80b 1356;;; iswitchb.el ends here