;; -*- Mode: Emacs-Lisp -*-
;; File: moccur.el
;; Description: multi-buffer occur mode
;; Author: Markus Freericks
;; Last Modified: 02-Aug-1991
;; Version: 1.1
;; LCD Archive Entry:
;; moccur|Markus Freericks|[email protected]|
;; multi-buffer occur mode|
;; 02-Aug-1991|1.1|~/modes/moccur.el.Z|
;; ========== Standard Disclaimer ==========
;; This file is not part of the GNU Emacs distribution (yet).
;; This file is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY. No author or distributor accepts
;; responsibility to anyone for the consequences of using it or for
;; whether it serves any particular purpose or works at all, unless he
;; says so in writing. Refer to the GNU Emacs General Public License
;; for full details. You should consider this code to be covered under
;; the terms of the GPL.
;; Everyone is granted permission to copy, modify and redistribute
;; this file, but only under the conditions described in the GNU Emacs
;; General Public License. A copy of this license is supposed to have
;; been given to you along with GNU Emacs so you can know your rights
;; and responsibilities. It should be in a file named COPYING. Among
;; other things, the copyright notice and this notice must be
;; preserved on all copies.
;; History
;; moccur 1.0 was released to the net on August 1st, 1991
;; [email protected] (Craig Steury) provided the exclusion list facility,
;; which was changed to to regexps and enhanced with a inclusion list.
;; Motivation
;; moccur is a major mode modelled after the 'Occur' mode of the
;; standard distribution. It is quite nice to use when you need to
;; work with a lot of buffers.
;;
;; Incompatibilites to Occur mode:
;; a) it browses through *all* buffers that have a file name
;; associated with them; those may or may not include the current
;; buffer. Especially, while standard occur works
;; on 'all lines following point', Moccur does not.
;; b) there is no support for the 'NLINE' argument.
;;
;; Usage:
;; moccur shows all occurrences of in all buffers
;; currently existing that refer to files.
;; the occurrences are displayed in a buffer running in Moccur mode;
;; C-c C-c gets you to the occurrence
(provide 'occur)
(defvar *moccur-buffer-name-exclusion-list* '("TAGS")
"Contains a list of regexprs against which each buffer's name is
tested when doing a moccur. Matching buffers are *not* searched for
occurrences. Per default, the TAGS file is excluded.")
(defvar *moccur-buffer-name-inclusion-list* '(".*")
"Contains a list of regexprs against which each buffer's name is
tested when doing a moccur. *Only* matching buffers are searched for
occurrences. Per default, this var contains only a \".*\"
catchall-regexp.")
(defun moccur-buffer-in-list-p (buffer-name buffer-name-regexps)
(cond ((null buffer-name-regexps) nil)
((eq (string-match (car buffer-name-regexps) buffer-name) 0) t)
(t (moccur-buffer-in-list-p buffer-name (cdr buffer-name-regexps)))))
(defun moccur-filter-buffers (buffer-list)
(cond ((null buffer-list) nil)
((and (moccur-buffer-in-list-p (buffer-name (car buffer-list))
*moccur-buffer-name-inclusion-list*)
(not (moccur-buffer-in-list-p (buffer-name (car buffer-list))
*moccur-buffer-name-exclusion-list*)))
(cons (car buffer-list)
(moccur-filter-buffers (cdr buffer-list))))
(t (moccur-filter-buffers (cdr buffer-list)))))
(defun moccur (regexp)
"Show all lines of all buffers containing a match for REGEXP.
The lines are shown in a buffer named *Moccur*.
It serves as a menu to find any of the occurrences in this buffer.
\\[describe-mode] in that buffer will explain how."
(interactive "sList lines matching regexp:")
(if (get-buffer "*Moccur*") ; there ought to be just one of these
(kill-buffer (get-buffer "*Moccur*")))
(let* ((buffers (moccur-filter-buffers (buffer-list)))
(occbuf (generate-new-buffer "*Moccur*"))
(matches 0)
(firstmatch t))
(set-buffer occbuf)
(insert "Lines matching " regexp "\n")
; (moccur-mode)
(while buffers
(if (not (buffer-file-name (car buffers)))
(setq buffers (cdr buffers))
(let ((currbuf (car buffers)))
(setq buffers (cdr buffers))
(set-buffer currbuf)
(goto-char (point-min))
(setq firstmatch t)
(while (re-search-forward regexp nil t)
(setq matches (+ matches 1))
(let* ((linenum (count-lines (point-min)(point)))
(tag (format "\n%3d " linenum)))
(save-excursion
(set-buffer occbuf)
(if firstmatch
(progn
(insert "Buffer: " (buffer-name currbuf)
" File: " (buffer-file-name currbuf) "\n")
(setq firstmatch nil)))
(insert tag))
(forward-word -1) ; needed if match goes to eoline
(beginning-of-line)
(let ((beg (point)))
(end-of-line)
(append-to-buffer occbuf beg (point)))
(forward-line nil)))
(save-excursion
(set-buffer occbuf)
(if (not firstmatch)(insert "\n\n"))))))
(if (> matches 0)
(save-excursion
(set-buffer occbuf)
(moccur-mode)
(goto-char (point-min))
(pop-to-buffer occbuf)
(message "%d matches" matches)
t)
(progn
(message "no matches")
nil))))
(defvar moccur-mode-map ())
(if moccur-mode-map
()
(setq moccur-mode-map (make-sparse-keymap))
(define-key moccur-mode-map "\C-c\C-c" 'moccur-mode-goto-occurrence))
(defun moccur-mode ()
"Major mode for output from \\[moccur].
Move point to one of the occurrences in this buffer,
then use \\[moccur-mode-goto-occurrence] to move to the buffer and
line where it was found.
\\{occur-mode-map}"
(kill-all-local-variables)
(use-local-map moccur-mode-map)
(setq major-mode 'moccur-mode)
(setq mode-name "Moccur"))
(defun moccur-mode-goto-occurrence ()
"Go to the line this occurrence was found in, in the buffer it was found in."
(interactive)
(if (not (eq major-mode 'moccur-mode))
(error "This is no moccur buffer")
(let ((beg nil)
(line nil)
(lineno nil)
(dstbuf nil))
(save-excursion
(beginning-of-line 1)
(setq beg (dot))
(end-of-line 1)
(setq line (buffer-substring beg (dot)))
(if (string-match "^[0-9]* " line)
(progn
(setq lineno (car (read-from-string line)))
(if (re-search-backward "^Buffer: ")
(progn
(search-forward " ")
(setq beg (dot))
(search-forward " ")
(setq line (buffer-substring beg (- (dot) 1)))
(setq dstbuf (get-buffer line))
(if (not dstbuf)
(message "buffer: <%s> doesn't exist anymore" line)))
(error "what did you do with the header?!")))
(error "this is no occurrence line!")))
(if (and lineno dstbuf)
(progn
(message "selectung <%s> line %d" line lineno)
(pop-to-buffer dstbuf)
(goto-line lineno))))))