aks@HUB.UCSB.EDU (Alan Stebbens) (01/03/91)
> Has anyone written programs to do address and telephone lists within > emacs? It would need to handle a database with name, address, and > telephone fields, sort by names, and output reports. Here is a copy of the "rolodex" package for Emacs. I am not the author; read the enclosed stuff. Alan Stebbens <aks@hub.ucsb.edu> (805) 893-3221 Center for Computational Sciences and Engineering (CCSE) University of California, Santa Barbara (UCSB) 3111 Engineering I, Santa Barbara, CA 93106 ============================= cut here =================================== #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: rolo-logic.el rolo-simple.el rolo.el # Wrapped by aks@anywhere on Wed Jan 2 12:24:19 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f rolo-logic.el -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rolo-logic.el\" else echo shar: Extracting \"rolo-logic.el\" \(7746 characters\) sed "s/^X//" >rolo-logic.el <<'END_OF_rolo-logic.el' X;;!emacs X;; X;; FILE: rolo-logic.el X;; SUMMARY: Performs logical retrievals on rolodex files X;; USAGE: GNU Emacs Lisp Library X;; X;; AUTHOR: Bob Weiner X;; ORG: Motorola, Inc., Communications Sector, Applied Research X;; E-MAIL: USENET: weiner@novavax.UUCP X;; X;; ORIG-DATE: 13-Jun-89 at 22:57:33 X;; LAST-MOD: 16-Jun-89 at 18:05:05 by Bob Weiner X;; X;; Copyright (C) 1989 Bob Weiner and Free Software Foundation, Inc. X;; Available for use and distribution under the same terms as GNU Emacs. X;; X;; This file is not yet part of GNU Emacs. X;; X;; DESCRIPTION: X;; X;; INSTALLATION: X;; X;; See also rolo.el. These functions are separated from rolo.el since many X;; users may never want or need them. They can be automatically loaded when X;; desired by adding the following to one of your Emacs init files: X;; X;; (autoload 'rolo-logic "rolo-logic" X;; "Logical rolodex search filters." X;; t) X;; X;; FEATURES: X;; X;; 1. One command, 'rolo-logic' which takes a logical search expression as X;; an argument and displays any matching entries. X;; X;; 2. Logical 'and', 'or', 'not', and 'xor' rolodex entry retrieval filter X;; functions. They take any number of string or boolean arguments and X;; may be nested. NOTE THAT THESE FUNCTIONS SHOULD NEVER BE CALLED X;; DIRECTLY UNLESS THE FREE VARIABLES 'start' and 'end' ARE BOUND X;; BEFOREHAND. X;; X;; EXAMPLE: X;; X;; (rolo-logic '(lambda () X;; (rolo-and X;; (rolo-xor "secretary" "Tool-And-Die") X;; "secretary"))) X;; X;; would find all non-Tool-And-Die Corp. secretaries in your rolodex. X;; X;; X;; X;; The logical matching routines are not really optimal, but then most X;; rolodex files are not terribly lengthy either. X;; X;; DESCRIP-END. X X(require 'rolo) X X(defun rolo-logic (func &optional in-bufs count-only include-sub-entries X no-sub-entries-out) X "Apply FUNC to all entries in optional IN-BUFS, display entries where FUNC is non-nil. XIf IN-BUFS is nil, 'rolo-file-list' is used. If optional COUNT-ONLY is Xnon-nil, don't display entries, return count of matching entries only. If Xoptional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC will be applied across all Xsub-entries at once. Default is to apply FUNC to each entry and sub-entry Xseparately. Entries are displayed with all of their sub-entries unless XINCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil. XFUNC should use the free variables 'start' and 'end' which contain the limits Xof the region on which it should operate. Returns number of applications of XFUNC that return non-nil." X (interactive "xLogic function of no arguments, (lambda () (<function calls>): ") X (let ((obuf (current-buffer)) X (display-buf (if count-only X nil X (prog1 (set-buffer (get-buffer-create rolo-display-buffer)) X (setq buffer-read-only nil) X (erase-buffer))))) X (let ((result X (mapcar X '(lambda (in-bufs) X (rolo-map-logic func in-bufs count-only include-sub-entries X no-sub-entries-out)) X (cond ((null in-bufs) rolo-file-list) X ((listp in-bufs) in-bufs) X ((list in-bufs)))))) X (let ((total-matches (apply '+ result))) X (if (or count-only (= total-matches 0)) X nil X (pop-to-buffer display-buf) X (goto-char (point-min)) X (set-buffer-modified-p nil) X (setq buffer-read-only t) X (let ((buf (get-buffer-window obuf))) X (if buf (select-window buf) (switch-to-buffer buf)))) X (if (interactive-p) X (message (concat (if (= total-matches 0) "No" total-matches) X " matching entr" X (if (= total-matches 1) "y" "ies") X " found in rolodex."))) X total-matches)))) X X(defun rolo-map-logic (func rolo-buf &optional count-only X include-sub-entries no-sub-entries-out) X "Apply FUNC to all entries in ROLO-BUF, write to buffer entries where FUNC is non-nil. XIf optional COUNT-ONLY is non-nil, don't display entries, return count of Xmatching entries only. If optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC Xwill be applied across all sub-entries at once. Default is to apply FUNC to Xeach entry and sub-entry separately. Entries are displayed with all of their Xsub-entries unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT Xflag is non-nil. FUNC should use the free variables 'start' and 'end' which Xcontain the limits of the region on which it should operate. Returns number Xof applications of FUNC that return non-nil." X (if (or (bufferp rolo-buf) X (if (file-exists-p rolo-buf) X (setq rolo-buf (find-file-noselect rolo-buf t)))) X (let* ((display-buf (set-buffer (get-buffer-create rolo-display-buffer))) X (buffer-read-only)) X (let ((hdr-pos) (num-found 0)) X (set-buffer rolo-buf) X (goto-char (point-min)) X (if (re-search-forward rolo-hdr-regexp nil t 2) X (progn (forward-line) X (setq hdr-pos (cons (point-min) (point))))) X (let* ((start) X (end) X (end-entry-hdr) X (curr-entry-level)) X (while (re-search-forward rolo-entry-regexp nil t) X (setq start (save-excursion (beginning-of-line) (point)) X next-entry-exists nil X end-entry-hdr (point) X curr-entry-level (buffer-substring start end-entry-hdr) X end (rolo-to-entry-end include-sub-entries curr-entry-level)) X (let ((fun (funcall func))) X (or count-only X (and fun (= num-found 0) hdr-pos X (append-to-buffer display-buf X (car hdr-pos) (cdr hdr-pos)))) X (if fun X (progn (goto-char end) X (setq num-found (1+ num-found) X end (if (or include-sub-entries X no-sub-entries-out) X end X (goto-char (rolo-to-entry-end X t curr-entry-level)))) X (or count-only X (append-to-buffer display-buf start end))) X (goto-char end-entry-hdr))))) X num-found)) X 0)) X X X;; X;; INTERNAL FUNCTIONS. X;; X X;; Do NOT call the following functions directly. X;; Send them as parts of a lambda expression to 'rolo-logic'. X X(defun rolo-not (&rest list-of-pats) X "Logical <not> rolodex entry filter. LIST-OF-PATS is a list of pattern elements. XEach element may be t, nil, or a string." X (let ((pat-list list-of-pats) X (pat)) X (while (and pat-list X (or (not (setq pat (car pat-list))) X (and (not (eq pat t)) X (goto-char start) X (not (search-forward pat end t))))) X (setq pat-list (cdr pat-list))) X (if pat-list nil t))) X X(defun rolo-or (&rest list-of-pats) X "Logical <or> rolodex entry filter. LIST-OF-PATS is a list of pattern elements. XEach element may be t, nil, or a string." X (let ((pat-list list-of-pats) X (pat)) X (while (and pat-list X (or (not (setq pat (car pat-list))) X (and (not (eq pat t)) X (goto-char start) X (not (search-forward pat end t))))) X (setq pat-list (cdr pat-list))) X (if pat-list t nil))) X X(defun rolo-xor (&rest list-of-pats) X "Logical <xor> rolodex entry filter. LIST-OF-PATS is a list of pattern elements. XEach element may be t, nil, or a string." X (let ((pat-list list-of-pats) X (pat) X (matches 0)) X (while (and pat-list X (or (not (setq pat (car pat-list))) X (and (or (eq pat t) X (not (goto-char start)) X (search-forward pat end t)) X (setq matches (1+ matches))) X t) X (< matches 2)) X (setq pat-list (cdr pat-list))) X (= matches 1))) X X(defun rolo-and (&rest list-of-pats) X "Logical <and> rolodex entry filter. LIST-OF-PATS is a list of pattern elements. XEach element may be t, nil, or a string." X (let ((pat-list list-of-pats) X (pat)) X (while (and pat-list X (setq pat (car pat-list)) X (or (eq pat t) X (not (goto-char start)) X (search-forward pat end t))) X (setq pat-list (cdr pat-list))) X (if pat-list nil t))) X X(provide 'rolo-logic) END_OF_rolo-logic.el if test 7746 -ne `wc -c <rolo-logic.el`; then echo shar: \"rolo-logic.el\" unpacked with wrong size! fi # end of overwriting check fi if test -f rolo-simple.el -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rolo-simple.el\" else echo shar: Extracting \"rolo-simple.el\" \(2466 characters\) sed "s/^X//" >rolo-simple.el <<'END_OF_rolo-simple.el' X;;!emacs X;; X;; FILE: rolo-simple.el X;; SUMMARY: Very simple routines to display entries matching a string X;; from a rolodex file. For those who find "rolo.el" too X;; intimidating. X;; USAGE: GNU Emacs Lisp Library X;; X;; AUTHOR: Bob Weiner X;; ORG: Motorola, Inc., Communications Sector, Applied Research X;; E-MAIL: USENET: weiner@novavax.UUCP X;; X;; ORIG-DATE: 7-Jun-89 at 22:08:29 X;; LAST-MOD: 16-Jun-89 at 00:27:20 by Bob Weiner X;; X;; Copyright (C) 1989 Bob Weiner and Free Software Foundation, Inc. X;; Available for use and distribution under the same terms as GNU Emacs. X;; X;; This file is not part of GNU Emacs. X;; X;; DESCRIPTION: X;; DESCRIP-END. X X(defconst rolo-file "~/.rolodex.otl" X "User-specific file in which rolodex entries are stored.") X X(defconst rolo-entry-regexp "^\*+" X "Regular expression to match the beginning of a rolodex entry.") X X(defconst rolo-hdr-regexp "^===" X "Regular expression to match the last line of the rolodex file header. XThis header is inserted into rolo-display-buffer before any entries are Xadded.") X X(defconst rolo-display-buffer "*Rolodex*" X "Buffer used to display set of last matching rolodex entries.") X X(defun rolo-fgrep (string) X "Find entries in rolo-file matching STRING. XThe rolo-file consists of a header terminated by a line which matches Xrolo-hdr-regexp. And rolodex entries beginning with rolo-entry-regexp." X (interactive "sRolodex string to match: ") X (let ((obuf (current-buffer))) X (save-excursion X (set-buffer (get-buffer-create rolo-display-buffer)) X (erase-buffer) X (find-file rolo-file) X (goto-char (point-min)) X (save-excursion X (if (re-search-forward rolo-hdr-regexp nil t) X (progn (forward-line) X (append-to-buffer rolo-display-buffer X (point-min) (point))))) X (re-search-forward rolo-entry-regexp nil t) X (beginning-of-line) X (while (search-forward string nil t) X (re-search-backward rolo-entry-regexp nil t) X (let ((start (point))) X (if (re-search-forward rolo-entry-regexp nil t 2) X (beginning-of-line) X (goto-char (point-max))) X (append-to-buffer rolo-display-buffer start (point))))) X (pop-to-buffer rolo-display-buffer) X (set-buffer-modified-p nil) X (select-window (get-buffer-window obuf)))) X X(defun rolo-edit () X "Display user-specific rolodex file for editing." X (interactive) X (find-file rolo-file)) X X(provide 'rolo) END_OF_rolo-simple.el if test 2466 -ne `wc -c <rolo-simple.el`; then echo shar: \"rolo-simple.el\" unpacked with wrong size! fi # end of overwriting check fi if test -f rolo.el -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"rolo.el\" else echo shar: Extracting \"rolo.el\" \(16052 characters\) sed "s/^X//" >rolo.el <<'END_OF_rolo.el' X;;!emacs X;; X;; FILE: rolo.el X;; SUMMARY: Retrieves and sorts entries from a list of rolodex files X;; USAGE: GNU Emacs Lisp Library X;; X;; AUTHOR: Bob Weiner X;; ORG: Motorola, Inc., Communications Sector, Applied Research X;; E-MAIL: USENET: weiner@novavax.UUCP X;; X;; ORIG-DATE: 7-Jun-89 at 22:08:29 X;; LAST-MOD: 16-Jun-89 at 14:56:11 by Bob Weiner X;; X;; Copyright (C) 1989 Bob Weiner and Free Software Foundation, Inc. X;; Available for use and distribution under the same terms as GNU Emacs. X;; X;; This file is not yet part of GNU Emacs. X;; This could use a key or field limited searching capability. X;; X;; DESCRIPTION: X;; X;; All I wanted to do was look up a phone number quickly . . . X;; X;; FEATURES: X;; X;; 1. Multiple rolodex files. X;; X;; 2. Hierarchical rolodex entries as in: X;; * Company X;; ** Manager X;; *** Underlings X;; X;; Searching for Manager turns up all Underlings. Searching for X;; Company retrieves all listed employees. X;; X;; This hierarchical system has proved very effective for retrieving X;; computer system administration problem reports by vendor name, X;; problem number or by subject area without having to resort to a X;; database system. X;; X;; 4. String and regular expression searching capabilities. Ability to X;; restrict number of matches or to report number of matches without X;; displaying entries. X;; X;; 5. Smart sorting of entries by hierarchy level. X;; X;; See "rolo-logic.el" for logical search functions (and, or, not, xor). X;; X;; X;; FOR NON-PROGRAMMERS: X;; X;; Modify the second file entry in the definition of 'rolo-file-list' X;; before using this package. X;; X;; To add personal files to rolo-file-list--when you find these functions are X;; useful for any sort of list lookup--add the following to your ~/.emacs X;; file (substituting where you see <fileN>): X;; X;; (require 'rolo) X;; (setq rolo-file-list (append rolo-file-list '("<file1>" "<file2>"))) X;; X;; The only command you absolutely need that is defined here is X;; 'rolo-fgrep'; it locates any matching entries in a set of rolodex files. X;; I recommend that you add the following key binding to one of your site X;; specific Emacs initialization files: X;; X;; (global-set-key "\C-x4r" 'rolo-fgrep) X;; X;; Calling 'rolo-fgrep' with a prefix argument limits the number of matches X;; to the specified number of entries. X;; X;; The following commands are also provided: X;; 'rolo-grep' finds all entries matching a regular expression in a set X;; of rolodex files; X;; 'rolo-edit' edits one's personal rolodex file; X;; 'rolo-sort' sorts all levels of entries in a rolodex file. X;; X;; To make the 'rolo' library load whenever you initially call any of these X;; functions, add the following to any of your Emacs init files: X;; X;; (autoload 'rolo-fgrep "rolo" X;; "Find entries in rolodex." X;; t) X;; (autoload 'rolo-grep "rolo" X;; "Find entries in rolodex." X;; t) X;; (autoload 'rolo-edit "rolo" X;; "Edit personal rolodex file." X;; t) X;; (autoload 'rolo-sort "rolo" X;; "Sort rolodex file." X;; t) X;; X;; X;; Entries in rolodex files are separated by patterns matching X;; 'rolo-entry-regexp'. Each entry may have any number of sub-entries X;; which represent the next level down in the entry hierarchy. X;; Sub-entries' separator patterns are always longer than their parents'. X;; For example, if an entry began with '*' then its sub-entries would begin X;; with '**' and so on. Blank lines in rolodex files will not end up where X;; you want them if you use the rolo-sort commands; therefore, blank lines X;; are not recommended. X;; X;; The reasons that the entries in 'rolo-file-list' have ".otl" suffixes X;; are so that they do not conflict with file names that other rolodex X;; programs might use and so that they are edited in 'outline-mode' by X;; default. If you want the latter behavior, uncomment and add something X;; like the following to one of your GNU Emacs initialization files: X;; X;; ;; Add to the list of suffixes that causes automatic mode invocation X;; (setq auto-mode-alist X;; (append '(("\\.otl$" . outline-mode)) auto-mode-alist)) X;; X;; Here is a snippet from our group rolodex file (the ';'s should be X;; removed of course and the '*'s should begin at the start of the line): X;; X;;============================================================================= X;; GROUP ROLODEX X;; <Last Name>, <First Name> <Co/Categ> W<Work #> H<Home #> P<Pager #> X;; F<Fax #> M<Modem #> C<Cellular #> X;; R<Other-radio #> X;; <Address> <Miscellaneous Info, Key Words> X;;============================================================================= X;;* EX594, Digital-Systems-Research X;;** Weiner, Bob Motorola W2087 P7-7489 X;; FL19, L-1035 X;; X;; X;; FOR PROGRAMMERS: X;; X;; If you change the value of 'rolo-entry-regexp', you will have to modify X;; 'rolo-sort'. X;; X;; The following additional functions are provided: X;; 'rolo-sort-level' sorts a specific level of entries in a rolodex file; X;; 'rolo-map-level' runs a user specified function on a specific level of X;; entries in a rolodex file. X;; 'rolo-fgrep-file', same as 'rolo-fgrep' but operates on a single file X;; 'rolo-grep-file, same as 'rolo-grep' but operates on a single file X;; X;; The buffers containing the rolodex files are not killed after a search X;; on the assumption that another search is likely to follow within this X;; Emacs session. You may wish to change this behavior. X;; X;; This code works fine on properly formatted rolodex files but probably X;; will fail on certain improperly formatted ones. X;; X;; DESCRIP-END. X X(defvar rolo-file-list '("~/.rolodex.otl") X "*List of files containing rolodex entries. XThe first file should be a user-specific rolodex file, typically in the home Xdirectory. The second file is often a shared, group-specific rolodex file. X XA rolo-file consists of: X (1) an optional header beginning with and ending with a line which matches X rolo-hdr-regexp; X (2) one or more rolodex entries beginning with rolo-entry-regexp, which X may be nested.") X X(defconst rolo-entry-regexp "^\*+" X "Regular expression to match the beginning of a rolodex entry. XThis pattern must match the beginning of the line. Entries may be nested Xthrough the use of increasingly longer beginning patterns.") X X(defconst rolo-hdr-regexp "^===" X "Regular expression to match the first and last lines of rolodex file headers. XThis header is inserted into rolo-display-buffer before any entries from the Xfile are added.") X X(defconst rolo-display-buffer "*Rolodex*" X "Buffer used to display set of last matching rolodex entries.") X X(defun rolo-fgrep (string &optional max-matches rolo-file count-only) X "Display rolodex entries matching STRING, to a maximum of prefix arg MAX-MATCHES, Xin file(s) from optional ROLO-FILE or rolo-file-list. Default is to find all Xmatching entries. Each entry is displayed with all of its sub-entries. XOptional COUNT-ONLY non-nil means don't display matching entries. XReturns number of entries matched. See also documentation for the variable Xrolo-file-list." X (interactive "sRolodex string to match: \nP") X (let ((total-matches X (rolo-grep (regexp-quote string) max-matches rolo-file count-only))) X (if (interactive-p) X (message (concat (if (= total-matches 0) "No" total-matches) X " matching entr" X (if (= total-matches 1) "y" "ies") X " found in rolodex."))) X total-matches)) X X(defun rolo-grep (regexp &optional max-matches rolo-bufs count-only) X "Display rolodex entries matching REGEXP, to a maximum of prefix arg MAX-MATCHES, Xin buffer(s) from optional ROLO-BUFS or rolo-file-list. Default is to find all Xmatching entries. Each entry is displayed with all of its sub-entries. XOptional COUNT-ONLY non-nil means don't display matching entries. XReturns number of entries matched. See also documentation for the variable Xrolo-file-list." X (interactive "sRolodex regular expression to match: \nP") X (let ((rolo-file-list X (cond ((null rolo-bufs) rolo-file-list) X ((listp rolo-bufs) rolo-bufs) X ((list rolo-bufs)))) X (obuf (current-buffer)) X (display-buf (if count-only X nil X (set-buffer (get-buffer-create rolo-display-buffer)))) X (total-matches 0)) X (if count-only nil (setq buffer-read-only nil) (erase-buffer)) X (mapcar '(lambda (file) X (if (or (null max-matches) (> max-matches 0)) X (let ((num-matched X (rolo-grep-file file regexp max-matches count-only))) X (setq total-matches (+ total-matches num-matched)) X (or (null max-matches) X (setq max-matches (- max-matches num-matched)))))) X rolo-file-list) X (if (or count-only (= total-matches 0)) X nil X (pop-to-buffer display-buf) X (goto-char (point-min)) X (set-buffer-modified-p nil) X (setq buffer-read-only t) X (let ((buf (get-buffer-window obuf))) X (if buf (select-window buf) (switch-to-buffer buf)))) X (if (interactive-p) X (message (concat (if (= total-matches 0) "No" total-matches) X " matching entr" X (if (= total-matches 1) "y" "ies") X " found in rolodex."))) X total-matches)) X X(defun rolo-edit () X "Display personal rolodex file for editing." X (interactive) X (find-file (car rolo-file-list))) X X(defun rolo-sort (&optional rolo-file) X "Sort up to 14 levels of entries in ROLO-FILE (default is personal rolodex file). XUses default rolo-entry-regexp for sort. Returns list of number of groupings Xat each entry level." X (interactive "fRolodex file to sort: ") X (if (not rolo-file) (setq rolo-file (car rolo-file-list))) X (let ((level-regexp (regexp-quote "**************")) X (entries-per-level-list) X (n)) X (while (not (equal level-regexp "")) X (setq n (rolo-sort-level rolo-file level-regexp)) X (if (or (/= n 0) entries-per-level-list) X (setq entries-per-level-list X (append (list n) entries-per-level-list))) X (setq level-regexp (substring level-regexp 0 (- (length level-regexp) 2)))) X entries-per-level-list)) X X(defun rolo-sort-level (rolo-file level-regexp &optional max-groupings) X "Sort groupings of entries in ROLO-FILE at hierarchy level given by LEVEL-REGEXP Xto a maximum of optional MAX-GROUPINGS. Nil value of MAX-GROUPINGS means all Xgroupings at the given level. LEVEL-REGEXP should simply match the text of Xany rolodex entry of the given level, not the beginning of a line (^); an Xexample, might be (regexp-quote \"**\") to match level two. Returns number Xof groupings sorted." X (interactive "sRolodex file to sort: \nRegexp to match text of level's entries: \nP") X (rolo-map-level X '(lambda (start end) (sort-lines nil start end)) X rolo-file X level-regexp X max-groupings)) X X(defun rolo-map-level (func rolo-buf level-regexp &optional max-groupings) X "Perform FUNC on each grouping of ROLO-BUF entries at hierarchy level LEVEL-REGEXP Xto a maximum of optional argument MAX-GROUPINGS. Nil value of MAX-GROUPINGS Xmeans all groupings at the given level. FUNC should take two arguments, the Xstart and the end of the region that it should manipulate. LEVEL-REGEXP Xshould simply match the text of any rolodex entry of the given level, not the Xbeginning of a line (^); an example, might be (regexp-quote \"**\") to match Xlevel two. Returns number of groupings matched." X (if (and (or (null max-groupings) (< 0 max-groupings)) X (or (bufferp rolo-buf) X (if (file-exists-p rolo-buf) X (setq rolo-buf (find-file-noselect rolo-buf t))))) X (let ((num-found 0) X (exact-level-regexp (concat "^\\(" level-regexp "\\)[ \t\n]")) X (outline-regexp rolo-entry-regexp) X (level-len)) X ;; Load 'outline' library since its functions are used here. X (if (not (boundp 'outline-mode-map)) X (load-library "outline")) X (set-buffer rolo-buf) X (goto-char (point-min)) X ;; Pass buffer header if it exists X (if (re-search-forward rolo-hdr-regexp nil t 2) X (forward-line)) X (while (and (or (null max-groupings) (< num-found max-groupings)) X (re-search-forward exact-level-regexp nil t)) X (setq num-found (1+ num-found)) X (let* ((opoint (prog1 (point) (beginning-of-line))) X (grouping-start (point)) X (start grouping-start) X (level-len (or level-len (- (1- opoint) start))) X (next-level-len) X (next-entry-exists) X (grouping-end) X (no-subtree)) X (while (and (progn X (if (setq next-entry-exists X (re-search-forward rolo-entry-regexp nil t 2)) X (setq next-level-len (- (point) X (progn (beginning-of-line) X (point))) X grouping-end (< next-level-len level-len) X no-subtree (<= next-level-len level-len)) X (setq grouping-end t no-subtree t) X (goto-char (point-max))) X (let ((end (point))) X (goto-char start) X (hide-subtree) ; And hide multiple lines of entry X ;; Move to start of next entry at equal or higher level X (setq start X (if no-subtree X end X (if (re-search-forward rolo-entry-regexp X nil t) X (progn (beginning-of-line) (point)) X (point-max)))) X ;; Remember last expression in 'progn' must always X ;; return non-nil X (goto-char start))) X (not grouping-end))) X (let ((end (point))) X (goto-char grouping-start) X (funcall func grouping-start end) X (goto-char end)))) X (show-all) X num-found) X 0)) X X(defun rolo-fgrep-file (rolo-buf string &optional max-matches count-only) X "Retrieve entries in ROLO-BUF matching STRING to a maximum of optional MAX-MATCHES. XNil value of MAX-MATCHES means find all matches. Optional COUNT-ONLY non-nil Xmeans don't retrieve matching entries. Returns number of matching entries Xfound." X (rolo-grep-file rolo-buf (regexp-quote string) max-matches count-only)) X X(defun rolo-grep-file (rolo-buf regexp &optional max-matches count-only) X "Retrieve entries in ROLO-BUF matching REGEXP to a maximum of optional MAX-MATCHES. XNil value of MAX-MATCHES means find all matches. Optional COUNT-ONLY non-nil Xmeans don't retrieve matching entries. Returns number of matching entries Xfound." X (if (and (or (null max-matches) (< 0 max-matches)) X (or (bufferp rolo-buf) X (if (file-exists-p rolo-buf) X (setq rolo-buf (find-file-noselect rolo-buf t))))) X (let ((hdr-pos) (num-found 0) (curr-entry-level)) X (set-buffer rolo-buf) X (goto-char (point-min)) X (if (re-search-forward rolo-hdr-regexp nil t 2) X (progn (forward-line) X (setq hdr-pos (cons (point-min) (point))))) X (re-search-forward rolo-entry-regexp nil t) X (while (and (or (null max-matches) (< num-found max-matches)) X (re-search-forward regexp nil t)) X (re-search-backward rolo-entry-regexp nil t) X (let ((start (point)) X (next-entry-exists)) X (re-search-forward rolo-entry-regexp nil t) X (rolo-to-entry-end X t (setq curr-entry-level (buffer-substring start (point)))) X (or count-only X (and (= num-found 0) hdr-pos X (progn (append-to-buffer rolo-display-buffer X (car hdr-pos) (cdr hdr-pos))))) X (setq num-found (1+ num-found)) X (or count-only X (append-to-buffer rolo-display-buffer start (point))))) X num-found) X 0)) X X;; X;; INTERNAL FUNCTIONS. X;; X X(defun rolo-to-entry-end (&optional include-sub-entries curr-entry-level) X"Go to end of whole entry if optional INCLUDE-SUB-ENTRIES is non-nil. XCURR-ENTRY-LEVEL is a string whose length is the same as the last found entry Xheader. If INCLUDE-SUB-ENTRIES is nil, CURR-ENTRY-LEVEL is not needed." X (while (and (setq next-entry-exists X (re-search-forward rolo-entry-regexp nil t)) X include-sub-entries X (> (- (point) (save-excursion X (beginning-of-line) X (point))) X (length curr-entry-level)))) X (if next-entry-exists X (progn (beginning-of-line) (point)) X (goto-char (point-max)))) X X X(provide 'rolo) END_OF_rolo.el if test 16052 -ne `wc -c <rolo.el`; then echo shar: \"rolo.el\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of shell archive. exit 0