Mercurial > hg > xemacs-beta
diff lisp/hyperbole/hmoccur.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 4103f0995bd7 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/hyperbole/hmoccur.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,211 @@ +;;!emacs +;; +;; FILE: hmoccur.el +;; SUMMARY: Multi-buffer or multi-file regexp occurrence location. +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: hypermedia, matching +;; +;; AUTHOR: Markus Freericks <mfx@cs.tu-berlin.de> / Bob Weiner +;; ORG: Technical University of Berlin / Brown U. +;; +;; ORIG-DATE: 1-Aug-91 +;; LAST-MOD: 14-Apr-95 at 16:04:43 by Bob Weiner +;; +;; This file is part of Hyperbole. +;; Available for use and distribution under the same terms as GNU Emacs. +;; +;; Copyright (C) 1991, Markus Freericks +;; Copyright (C) 1991-1995, Free Software Foundation, Inc. +;; Developed with support from Motorola Inc. +;; +;; DESCRIPTION: +;; +;; Modified by Bob Weiner to allow selection of a set of files within a +;; single directory to search. By default, {M-x moccur RTN} searches +;; current buffers with files attached. +;; +;; Date: 1 Aug 91 15:47:27 GMT +;; From: mfx@cs.tu-berlin.de (Markus Freericks) +;; Subject: moccur - multibuffer occurences +;; +;; While editing some dozen or so files, i had the dire need for +;; something like 'occur' that can cope with multiple buffers. This has +;; probably been done before; but still, here is my try at it. It seems +;; to be very useful. +;; +;; How to use it: simple say +;; M-x moccur <regexp> +;; moccur then searches through *all buffers* currently existing that are +;; bound to files and displays the occurences in a buffer that runs in +;; Moccur-mode. Change to that buffer, scroll around, and say C-c C-c +;; to jump to the occurrence. Quite simple. +;; +;; 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 <regexp> shows all occurences of <regexp> in all buffers +;; currently existing that refer to files. +;; the occurences are displayed in a buffer running in Moccur mode; +;; C-c C-c gets you to the occurence +;; +;; DESCRIP-END. + +;;; ************************************************************************ +;;; Public variables +;;; ************************************************************************ + +(defconst moccur-source-prefix "@loc> " + "Prefix for lines indicating source of matches.") + +;;; ************************************************************************ +;;; Public functions +;;; ************************************************************************ + +(defun moccur (regexp &optional file-regexp no-fold-search) + "Show all lines of all buffers containing a match for REGEXP. +With optional FILE-REGEXP, a pattern matching to files in a single +directory, search matching files rather than current buffers. +The lines are shown in a buffer named *Moccur* which serves as a menu to +find any of the occurrences in this buffer. +\\[describe-mode] in that buffer explains how." + (interactive "sRegexp to find occurrences of: \nsFiles to search (default current file buffers): ") + (if (equal file-regexp "") (setq file-regexp nil)) + (let* ((buffers (if file-regexp (directory-files + (expand-file-name + (or (file-name-directory + file-regexp) ".")) + 'full (file-name-nondirectory file-regexp)) + (buffer-list))) + (occbuf (get-buffer-create "*Moccur*")) + (matches 0) + (firstmatch t)) + (set-buffer occbuf) + (setq buffer-read-only nil) + (widen) + (erase-buffer) + (insert "Lines matching '" regexp "':\n\n") + (let ((currbuf) (currfile) (kill-buf)) + (while buffers + (setq currbuf (car buffers) + currfile (if (stringp currbuf) currbuf) + kill-buf (and currfile (not (get-file-buffer currfile))) + buffers (cdr buffers)) + (if currfile + (setq currbuf (find-file-noselect currfile)) + (setq currfile (buffer-file-name currbuf))) + (if (or (not currfile) (not currbuf)) + nil + (set-buffer currbuf) + (let ((case-fold-search (not no-fold-search))) + (save-excursion + (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%4d:" linenum))) + (set-buffer occbuf) + (if firstmatch + (progn + (insert moccur-source-prefix currfile "\n") + (setq firstmatch nil))) + (insert tag) + (set-buffer currbuf) + (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 1))))) + (save-excursion + (set-buffer occbuf) + (if (not firstmatch) (insert "\n\n")) + (if kill-buf (kill-buffer currbuf)))))) + (if (> matches 0) + (progn + (set-buffer occbuf) + (moccur-mode) + (if (fboundp 'outline-minor-mode) + (and (progn (goto-char 1) + (search-forward "\C-m" nil t)) + (outline-minor-mode 1))) + (goto-char (point-min)) + (pop-to-buffer occbuf) + (message "%d matches." matches) + t) + (message "No matches.") + nil))) + +(defun moccur-to () + "Go to the line where this occurrence was found." + (interactive) + (if (not (eq major-mode 'moccur-mode)) + (error "'moccur-to' must be called within a moccur buffer.") + (let ((beg nil) + (line nil) + (lineno nil) + (dstbuf nil)) + (save-excursion + (beginning-of-line) + (setq beg (point)) + (end-of-line) + (setq line (buffer-substring beg (point))) + (if (string-match "^[ ]*[0-9]+:" line) + (progn + (setq lineno (string-to-int (substring + line 0 (match-end 0)))) + (if (re-search-backward + (concat "^" moccur-source-prefix + "\"?\\([^\" \n]+\\)\"?") nil t) + (progn + (setq line (buffer-substring + (match-beginning 1) (match-end 1)) + dstbuf (find-file-noselect line)) + (if (not dstbuf) + (message + "moccur-to: file '%s' is not readable" line))) + (error "No moccur header line for file."))) + (error "Not an moccur occurrence line."))) + (if (and lineno dstbuf) + (progn + (message "Selection <%s> line %d." line lineno) + (pop-to-buffer dstbuf) + (goto-line lineno)))))) + +(fset 'moccur-mode-goto-occurrence 'moccur-to) + + +;;; ************************************************************************ +;;; Private functions +;;; ************************************************************************ + +(defun moccur-mode () + "Major mode for output from \\[moccur]. +Move point to one of the occurrences in this buffer, +then use \\[moccur-to] to go to the same occurrence +in the buffer that the occurrenc was found in. +\\{occur-mode-map}" + (kill-all-local-variables) + (use-local-map moccur-mode-map) + (setq major-mode 'moccur-mode) + (setq mode-name "Moccur")) + +;;; ************************************************************************ +;;; Private variables +;;; ************************************************************************ + +(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-to) + (define-key moccur-mode-map " " 'moccur-to) + (define-key moccur-mode-map "\C-m" 'moccur-to) +) + +(provide 'hmoccur)