;; -*- emacs-lisp -*- ;;; mst-iswitchb-narrow.el --- narrow the iswitch buffer to particular buffers ;; Author: Mark Triggs ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;;; Commentary: ;; This code allows quick navigation between buffers by 'narrowing' the iswitch ;; list based on a set of predefined predicates and/or regular expressions. For ;; example, hitting tab once might show only buffers whose major mode matches ;; the current buffer's major mode. Hitting again might show all .el files ;; currently open, again might show all the .lisp files currently open and so ;; on. ;; To use it, add something like the following to your ~/.emacs ;; (define-key global-map (kbd "C-x b") 'iswitchb-narrow) ;;; Code: (defvar interesting-buffers '((lambda (b) (eq (buffer-mode (current-buffer)) (buffer-mode b))) "\\.lisp$" "\\(^dot\\.\\|\\.el$\\)" "\\.jl$" "\\.py$" "\\.p[lm]$" "\\.c$" "\\.hs$" "\\.java" "\\.e$" "\\.\\(tex\\|bib\\)$" "\\.htm\\(l\\)?$" "\\.txt$") "A list of strings and/or predicates that denote groups of buffers that should be shown when hitting tab in iswitch. Strings are regexps which are matched against buffer names using STRING-MATCH. Predicates should be functions which take a buffer as a single argument, and return a boolean.") (defun iswitchb-buffer-narrow (predicate) (let ((matcher (if (stringp predicate) (lambda (b) (string-match predicate (buffer-name b))) predicate))) (if predicate (let ((iswitchb-make-buflist-hook (cons (lambda () (setq iswitchb-temp-buflist (remove-if-not matcher (buffer-list)))) iswitchb-make-buflist-hook))) (iswitchb-buffer)) (iswitchb-buffer)))) (defun iswitchb-narrow () (interactive) ;; the first call should show all buffers (next-interesting-buffer-identifier 'reset) (let ((iswitchb-minibuffer-setup-hook (list (lambda () (define-key iswitchb-mode-map "\t" (lambda () (interactive) (throw 'done 'next-set))))))) (while (eql 'next-set (catch 'done (iswitchb-buffer-narrow (next-interesting-buffer-identifier))))))) (defvar next-interesting-buffer-identifier 0) (defun next-interesting-buffer-identifier (&optional reset) "Return the next interesting file extension" (cond (reset (setq next-interesting-buffer-identifier (length interesting-buffers)) ; a hack, I know nil) (t (or (dolist (ext (nthcdr next-interesting-buffer-identifier interesting-buffers)) (incf next-interesting-buffer-identifier) (when (some (if (stringp ext) (lambda (b) (string-match ext (buffer-name b))) ext) (buffer-list)) (return ext))) (progn (setq next-interesting-buffer-identifier 0) nil))))) (provide 'mst-iswitchb-narrow) ;;; mst-iswitchb-narrow.el ends here