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