home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
browser2.zip
/
br-loop.el
< prev
next >
Wrap
Lisp/Scheme
|
1995-02-17
|
8KB
|
227 lines
;;; CLASS BROWSER FOR C++
;;; $Id: br-loop.el,v 3.1 1995/02/17 18:19:36 mmann Exp $
;;;
;;; **********************************************************************
;;; Copyright (C) 1993, 1994 Gerd Moellmann. All rights reserved.
;;; Altenbergstr. 6, D-40235 Duesseldorf, Germany
;;; 100025.3303@COMPUSERVE.COM
;;; Suggestions, comments and requests for improvements are welcome.
;;; **********************************************************************
;;;
;;; This version works with both Emacs version 18 and 19, and I want
;;; to keep it that way. It requires the CL-19 Common Lisp compatibility
;;; package for Emacs 18 and 19.
;;;
;;; Search and replace over files in tree.
;;;
;; This file may be made part of the Emacs distribution at the option
;; of the FSF.
;; This code 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.
;; Everyone is granted permission to copy, modify and redistribute
;; this code, 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.
(require 'cl-19 "cl")
(require 'backquote)
(require 'br-macro)
(require 'br-struc)
;;;
;;; Increase MAX-LISP-EVAL-DEPTH for Emacs 18. This is necessary to
;;; be able to compile nested LOOPs here.
;;;
(eval-when (compile)
(setq max-lisp-eval-depth (max 300 max-lisp-eval-depth)))
(defvar browse-loop-form ()
"Form for browse-loop-continue. Evaluated for each file in the
tree. If it returns NIL, goes on with the next file.")
(defvar browse-next-file-list ()
"A list of files to be processed for searching, replacing etc.")
(defvar browse-next-file-path nil
"The path relative to which files have to be searched.")
(defvar browse-loop-last-file nil
"The last file visited via browse-loop.")
;;;
;;; Return an obarray with all files that are mentioned in a tree.
;;; Only one entry for each file is in the list. If MARKED-ONLY is T,
;;; include marked classes only.
;;;
(defun* tree-files-obarray (&optional marked-only
&aux (files (make-vector 1023 0))
(i -1))
(dotrees (tree @tree-obarray)
(when (or (not marked-only)
(tree-mark tree))
(let* ((class (tree-class tree)))
(when (zerop (% (incf i) 20))
(browse-indicate-progress "Preparing file list" (zerop i)))
;; Add files mentioned in class description
(let ((source-file (class-source-file class))
(file (class-file class)))
(when source-file (intern source-file files))
(when file (intern file files)))
;; For all member lists in this class
(loop for accessor in member-lists do
(loop for m in (funcall accessor tree)
for file = (member-file m)
for def-file = (member-definition-file m) do
(when file (intern file files))
(when def-file (intern def-file files)))))))
files)
;;;
;;; Convert files obarray to list form.
;;;
(defun tree-files (&optional marked-only)
(loop for x being the symbols of (tree-files-obarray marked-only)
collect (symbol-name x)))
;;;
;;; Select next file among files in current tag table.
;;; Non-nil argument (prefix arg, if interactive) initializes to
;;; the beginning of the list of files in the tag table.
;;;
(defun browse-next-file (&optional initialize tree-buffer)
(interactive "P")
;; Call with INITIALIZE non-NIL initializes the files list.
;; If more than one tree buffer is loaded, let the user choose
;; on which tree (s)he wants to operate.
(when initialize
(let ((buffer (or tree-buffer (tree-choose-buffer))))
(save-excursion
(set-buffer buffer)
(setq browse-next-file-list (tree-files (tree-marked-exist-p))
browse-loop-last-file nil
browse-next-file-path
(file-name-directory @tags-filename)))))
;; End of the loop if the stack of files is empty.
(unless browse-next-file-list
(error "All files processed."))
;; BROWSE-LOOP-LAST-FILE is the last file that was visited due
;; to a call to BROWSE-LOOP (see below). If that file is still
;; in memory, and it wasn't modified, throw its buffer away to
;; prevent cluttering up the buffer list.
(when browse-loop-last-file
(let ((buffer (get-file-buffer browse-loop-last-file)))
(when (and buffer
(not (buffer-modified-p buffer)))
(kill-buffer buffer))))
;; Remember this buffer file name for later deletion, if it
;; wasn't visited by other means.
(let ((file (expand-file-name (car browse-next-file-list)
browse-next-file-path)))
(setq browse-loop-last-file (if (get-file-buffer file) nil file))
;; Find the file and pop the file list. Pop has to be done
;; before the file is loaded because FIND-FILE might encounter
;; an error, and we want to be able to proceed with the next
;; file in this case.
(pop browse-next-file-list)
(find-file file)))
;;;
;;; Repeat last operation.
;;;
;;;###autoload
(defun browse-loop (&optional first-time tree-buffer)
"Repeat last operation on files in tree."
(interactive)
(when first-time
(browse-next-file first-time tree-buffer)
(goto-char (point-min)))
(while (not (eval browse-loop-form))
(browse-next-file)
(message "Scanning file %s..." buffer-file-name)
(goto-char (point-min))))
;;;
;;; Search.
;;;
;;###autoload
(defun browse-search (regexp)
"Search for REGEXP in all files in tree. If marked classes exist, process
marked classes, only. If regular expression is empty go on with last search."
(interactive "sTree search (regexp): ")
(if (and (string= regexp "")
(eq (car browse-loop-form) 're-search-forward))
(browse-loop)
(setq browse-loop-form (list 're-search-forward regexp nil t))
(browse-loop 'first-time)))
;;;
;;; Query replace.
;;;
;;;###autoload
(defun browse-query-replace (from to)
"Perform query replace over all files in tree. With prefix arg,
process marked classes in the tree, only."
(interactive
"sTree query replace (regexp): \nsTree query replace %s by: ")
(setq browse-loop-form
(list 'and (list 'save-excursion
(list 're-search-forward from nil t))
(list 'not (list 'perform-replace from to t t nil))))
(browse-loop 'first-time))
;;;
;;; Search for some member with completion.
;;;
;;; ###autoload
(defun browse-search-member-usage (&optional fix-name)
"Read a member name from the minibuffer and search over files
in tree for something that looks like a call of a function with
that name."
(interactive)
(multiple-value-bind
(tree header tree-buffer)
(browse-find-tree)
(unless tree
(error "No class tree."))
(let ((name fix-name) class-name regexp)
(unless name
(multiple-value-setq (class-name name)
(browse-tags-read-name header "Find calls of: ")))
(setq regexp (concat "\\<" name "[ \t]*(")
browse-loop-form (list 're-search-forward regexp nil t))
(browse-loop 'first-time tree-buffer))))
;; end of `loop.el'.