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