1;;; isearchb --- a marriage between iswitchb and isearch 2 3;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. 4 5;; Author: John Wiegley <johnw@gnu.org> 6;; Maintainer: FSF 7;; Created: 16 Apr 2004 8;; Version: 1.5 9;; Keywords: lisp 10;; X-URL: http://www.newartisans.com/johnw/emacs.html 11 12;; This file is part of GNU Emacs. 13 14;; GNU Emacs is free software; you can redistribute it and/or modify 15;; it under the terms of the GNU General Public License as published by 16;; the Free Software Foundation; either version 2, or (at your option) 17;; any later version. 18 19;; GNU Emacs is distributed in the hope that it will be useful, 20;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22;; GNU General Public License for more details. 23 24;; You should have received a copy of the GNU General Public License 25;; along with GNU Emacs; see the file COPYING. If not, write to the 26;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 27;; Boston, MA 02110-1301, USA. 28 29;;; Commentary: 30 31;; This module allows you to switch to buffers even faster than with 32;; iswitchb! It is not intended to replace it, however, as it works 33;; well only with buffers whose names don't typically overlap. You'll 34;; have to try it first, and see how your mileage varies. 35;; 36;; The first way to use isearchb is by holding down a modifier key, in 37;; which case every letter you type while holding it searches for any 38;; buffer matching what you're typing (using the same ordering scheme 39;; employed by iswitchb). To use it this way, add to your .emacs: 40;; 41;; (isearchb-set-keybindings 'super) ; s-x s-y s-z now finds "xyz" 42;; 43;; The other way is by using a command that puts you into "search" 44;; mode, just like with isearch. I use C-z for this. The binding in 45;; my .emacs looks like: 46;; 47;; (define-key global-map [(control ?z)] 'isearchb-activate) 48;; 49;; Now, after pressing C-z (for example), each self-inserting 50;; character thereafter will search for a buffer containing those 51;; characters. For instance, typing "C-z xyz" will switch to the 52;; first buffer containing "xyz". Once you press a non-self-inserting 53;; character (such as any control key sequence), the search will end. 54;; 55;; C-z after C-z toggles between the previously selected buffer and 56;; the current one. 57;; 58;; C-g aborts the search and returns you to your original buffer. 59;; 60;; TAB, after typing in a few characters (after C-z), will jump into 61;; iswitchb, using the prefix you've typed so far. This is handy when 62;; you realize that isearchb is not powerful enough to find the buffer 63;; you're looking for. 64;; 65;; C-s and C-r move forward and backward in the buffer list. If 66;; `isearchb-show-completions' is non-nil (the default), the list of 67;; possible completions is shown in the minibuffer. 68;; 69;; If `isearchb-idle-timeout' is set to a number, isearchb will quit 70;; after that many seconds of idle time. I recommend trying it set to 71;; one or two seconds. Then, if you switch to a buffer and wait for 72;; that amount of time, you can start typing without manually exiting 73;; isearchb. 74 75;; TODO: 76;; C-z C-z is broken 77;; killing iswitchb.el and then trying to switch back is broken 78;; make sure TAB isn't broken 79 80(require 'iswitchb) 81 82(defgroup isearchb nil 83 "Switch between buffers using a mechanism like isearch." 84 :group 'iswitchb) 85 86(defcustom isearchb-idle-timeout nil 87 "*Number of idle seconds before isearchb turns itself off. 88If nil, don't use a timeout." 89 :type '(choice (integer :tag "Seconds") 90 (const :tag "Disable" nil)) 91 :group 'isearchb) 92 93(defcustom isearchb-show-completions t 94 "*If non-nil, show possible completions in the minibuffer." 95 :type 'boolean 96 :group 'isearchb) 97 98(defvar isearchb-start-buffer nil) 99(defvar isearchb-last-buffer nil) 100(defvar isearchb-idle-timer nil) 101 102(defun isearchb-stop (&optional return-to-buffer ignore-command) 103 "Called by isearchb to terminate a search in progress." 104 (remove-hook 'pre-command-hook 'isearchb-follow-char) 105 (if return-to-buffer 106 (switch-to-buffer isearchb-start-buffer) 107 (setq isearchb-last-buffer isearchb-start-buffer)) 108 (when isearchb-idle-timer 109 (cancel-timer isearchb-idle-timer) 110 (setq isearchb-idle-timer nil)) 111 (if ignore-command 112 (setq this-command 'ignore 113 last-command 'ignore)) 114 (message nil)) 115 116(defun isearchb-iswitchb () 117 "isearchb's custom version of the `iswitchb' command. 118Its purpose is to pass different call arguments to 119`iswitchb-read-buffer'." 120 (interactive) 121 (let* ((prompt "iswitch ") 122 (iswitchb-method 'samewindow) 123 (buf (iswitchb-read-buffer prompt nil nil iswitchb-text t))) 124 (if (eq iswitchb-exit 'findfile) 125 (call-interactively 'find-file) 126 (when buf 127 (if (get-buffer buf) 128 ;; buffer exists, so view it and then exit 129 (iswitchb-visit-buffer buf) 130 ;; else buffer doesn't exist 131 (iswitchb-possible-new-buffer buf)))))) 132 133(defun isearchb () 134 "Switch to buffer matching a substring, based on chars typed." 135 (interactive) 136 (unless (eq last-command 'isearchb) 137 (setq iswitchb-text nil)) 138 (unless iswitchb-text 139 (setq iswitchb-text "") 140 (iswitchb-make-buflist nil)) 141 (if last-command-char 142 (setq iswitchb-rescan t 143 iswitchb-text (concat iswitchb-text 144 (char-to-string last-command-char)))) 145 (iswitchb-set-matches) 146 (let* ((match (car iswitchb-matches)) 147 (buf (and match (get-buffer match)))) 148 (if (null buf) 149 (progn 150 (isearchb-stop t) 151 (isearchb-iswitchb)) 152 (switch-to-buffer buf) 153 (if isearchb-show-completions 154 (message "isearchb: %s%s" iswitchb-text 155 (iswitchb-completions iswitchb-text)) 156 (if (= 1 (length iswitchb-matches)) 157 (message "isearchb: %s (only match)" iswitchb-text) 158 (message "isearchb: %s" iswitchb-text)))))) 159 160(defun isearchb-set-keybindings (modifier) 161 "Setup isearchb on the given MODIFIER." 162 (dotimes (i 128) 163 (if (eq 'self-insert-command 164 (lookup-key global-map (vector i))) 165 (define-key global-map (vector (list modifier i)) 'isearchb)))) 166 167(defun isearchb-follow-char () 168 "Function added to `post-command-hook' to handle the isearchb \"mode\"." 169 (let (keys) 170 (if (not (and (memq last-command '(isearchb isearchb-activate)) 171 (setq keys (this-command-keys)) 172 (= 1 (length keys)))) 173 (isearchb-stop) 174 (cond 175 ((or (equal keys "\C-h") (equal keys "\C-?") 176 (equal keys [backspace]) (equal keys [delete])) 177 (setq iswitchb-text 178 (substring iswitchb-text 0 (1- (length iswitchb-text)))) 179 (if (= 0 (length iswitchb-text)) 180 (isearchb-stop t t) 181 (setq last-command-char nil) 182 (setq this-command 'isearchb))) 183 ((or (equal keys "\C-i") (equal keys [tab])) 184 (setq this-command 'isearchb-iswitchb)) 185 ((equal keys "\C-s") 186 (iswitchb-next-match) 187 (setq last-command-char nil) 188 (setq this-command 'isearchb)) 189 ((equal keys "\C-r") 190 (iswitchb-prev-match) 191 (setq last-command-char nil) 192 (setq this-command 'isearchb)) 193 ((equal keys "\C-g") 194 (ding) 195 (isearchb-stop t t)) 196 ((eq (lookup-key global-map keys) 'self-insert-command) 197 (setq this-command 'isearchb))) 198 (if (and isearchb-idle-timeout 199 (null isearchb-idle-timer)) 200 (setq isearchb-idle-timer 201 (run-with-idle-timer isearchb-idle-timeout nil 202 'isearchb-stop)))))) 203 204;;;###autoload 205(defun isearchb-activate () 206 "Active isearchb mode for subsequent alphanumeric keystrokes. 207Executing this command again will terminate the search; or, if 208the search has not yet begun, will toggle to the last buffer 209accessed via isearchb." 210 (interactive) 211 (cond 212 ((eq last-command 'isearchb) 213 (isearchb-stop nil t)) 214 ((eq last-command 'isearchb-activate) 215 (if isearchb-last-buffer 216 (switch-to-buffer isearchb-last-buffer) 217 (error "isearchb: There is no previous buffer to toggle to")) 218 (isearchb-stop nil t)) 219 (t 220 (message "isearchb: ") 221 (setq iswitchb-text nil 222 isearchb-start-buffer (current-buffer)) 223 (add-hook 'pre-command-hook 'isearchb-follow-char)))) 224 225(provide 'isearchb) 226 227;;; arch-tag: 9277523f-a624-4aa0-ba10-b89eeb7b6e99 228;;; isearchb.el ends here 229