1 ;;; wrolo-logic.el --- Performs logical retrievals on rolodex files
3 ;; Copyright (C) 1989-1995, Free Software Foundation, Inc.
4 ;; Developed with support from Motorola Inc.
6 ;; Author: Bob Weiner, Brown U.
7 ;; Maintainer: Mats Lidell <matsl@contactor.se>
8 ;; Keywords: hypermedia, matching
10 ;; This file is part of GNU Hyperbole.
12 ;; GNU Hyperbole is free software; you can redistribute it and/or
13 ;; modify it under the terms of the GNU General Public License as
14 ;; published by the Free Software Foundation; either version 3, or (at
15 ;; your option) any later version.
17 ;; GNU Hyperbole is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
31 ;; See also wrolo.el. These functions are separated from wrolo.el since many
32 ;; users may never want or need them. They can be automatically loaded when
33 ;; desired by adding the following to one of your Emacs init files:
35 ;; (autoload 'rolo-logic "wrolo-logic" "Logical rolodex search filters." t)
39 ;; 1. One command, 'rolo-logic' which takes a logical search expression as
40 ;; an argument and displays any matching entries.
42 ;; 2. Logical 'and', 'or', 'not', and 'xor' rolodex entry retrieval filter
43 ;; functions. They take any number of string or boolean arguments and
44 ;; may be nested. NOTE THAT THESE FUNCTIONS SHOULD NEVER BE CALLED
45 ;; DIRECTLY UNLESS THE FREE VARIABLES 'start' and 'end' ARE BOUND
50 ;; (rolo-logic (function
53 ;; (rolo-not "Tool-And-Die")
56 ;; would find all non-Tool-And-Die Corp. secretaries in your rolodex.
58 ;; The logical matching routines are not at all optimal, but then most
59 ;; rolodex files are not terribly lengthy either.
67 (defun rolo-logic (func &optional in-bufs count-only include-sub-entries
69 "Apply FUNC to all entries in optional IN-BUFS, display entries where FUNC is non-nil.
70 If IN-BUFS is nil, 'rolo-file-list' is used. If optional COUNT-ONLY is
71 non-nil, don't display entries, return count of matching entries only. If
72 optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC will be applied across all
73 sub-entries at once. Default is to apply FUNC to each entry and sub-entry
74 separately. Entries are displayed with all of their sub-entries unless
75 INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil.
76 FUNC should use the free variables 'start' and 'end' which contain the limits
77 of the region on which it should operate. Returns number of applications of
78 FUNC that return non-nil."
79 (interactive "xLogic function of no arguments, (lambda () (<function calls>): ")
80 (let ((obuf (current-buffer))
81 (display-buf (if count-only
83 (prog1 (set-buffer (get-buffer-create rolo-display-buffer))
84 (setq buffer-read-only nil)
90 (rolo-map-logic func in-bufs count-only include-sub-entries
92 (cond ((null in-bufs) rolo-file-list)
93 ((listp in-bufs) in-bufs)
95 (let ((total-matches (apply '+ result)))
96 (if (or count-only (= total-matches 0))
98 (pop-to-buffer display-buf)
99 (goto-char (point-min))
100 (set-buffer-modified-p nil)
101 (setq buffer-read-only t)
102 (let ((buf (get-buffer-window obuf)))
103 (if buf (select-window buf) (switch-to-buffer buf))))
105 (message (concat (if (= total-matches 0) "No" total-matches)
107 (if (= total-matches 1) "y" "ies")
108 " found in rolodex.")))
111 (defun rolo-map-logic (func rolo-buf &optional count-only
112 include-sub-entries no-sub-entries-out)
113 "Apply FUNC to all entries in ROLO-BUF, write to buffer entries where FUNC is non-nil.
114 If optional COUNT-ONLY is non-nil, don't display entries, return count of
115 matching entries only. If optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC
116 will be applied across all sub-entries at once. Default is to apply FUNC to
117 each entry and sub-entry separately. Entries are displayed with all of their
118 sub-entries unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT
119 flag is non-nil. FUNC should use the free variables 'start' and 'end' which
120 contain the limits of the region on which it should operate. Returns number
121 of applications of FUNC that return non-nil."
122 (if (or (bufferp rolo-buf)
123 (if (file-exists-p rolo-buf)
124 (setq rolo-buf (find-file-noselect rolo-buf t))))
125 (let* ((display-buf (set-buffer (get-buffer-create rolo-display-buffer)))
127 (let ((hdr-pos) (num-found 0))
128 (set-buffer rolo-buf)
129 (goto-char (point-min))
130 (if (re-search-forward rolo-hdr-regexp nil t 2)
131 (progn (forward-line)
132 (setq hdr-pos (cons (point-min) (point)))))
137 (while (re-search-forward rolo-entry-regexp nil t)
138 (setq start (save-excursion (beginning-of-line) (point))
139 next-entry-exists nil
140 end-entry-hdr (point)
141 curr-entry-level (buffer-substring start end-entry-hdr)
142 end (rolo-to-entry-end include-sub-entries curr-entry-level))
143 (let ((fun (funcall func)))
145 (and fun (= num-found 0) hdr-pos
146 (append-to-buffer display-buf
147 (car hdr-pos) (cdr hdr-pos))))
149 (progn (goto-char end)
150 (setq num-found (1+ num-found)
151 end (if (or include-sub-entries
154 (goto-char (rolo-to-entry-end
155 t curr-entry-level))))
157 (append-to-buffer display-buf start end)))
158 (goto-char end-entry-hdr)))))
159 (rolo-kill-buffer rolo-buf)
165 ;; INTERNAL FUNCTIONS.
168 ;; Do NOT call the following functions directly.
169 ;; Send them as parts of a lambda expression to 'rolo-logic'.
171 (defun rolo-not (&rest pat-list)
172 "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements.
173 Each element may be t, nil, or a string."
176 (or (not (setq pat (car pat-list)))
177 (and (not (eq pat t))
179 (not (search-forward pat end t)))))
180 (setq pat-list (cdr pat-list)))
181 (if pat-list nil t)))
183 (defun rolo-or (&rest pat-list)
184 "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements.
185 Each element may be t, nil, or a string."
186 (if (memq t pat-list)
190 (or (not (setq pat (car pat-list)))
191 (and (not (eq pat t))
193 (not (search-forward pat end t)))))
194 (setq pat-list (cdr pat-list)))
195 (if pat-list t nil))))
197 (defun rolo-xor (&rest pat-list)
198 "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements.
199 Each element may be t, nil, or a string."
203 (or (not (setq pat (car pat-list)))
205 (not (goto-char start))
206 (search-forward pat end t))
207 (setq matches (1+ matches)))
210 (setq pat-list (cdr pat-list)))
213 (defun rolo-and (&rest pat-list)
214 "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements.
215 Each element may be t, nil, or a string."
216 (if (memq nil pat-list)
220 (setq pat (car pat-list))
222 (not (goto-char start))
223 (search-forward pat end t)))
224 (setq pat-list (cdr pat-list)))
225 (if pat-list nil t))))
227 ;; Work with regular expression patterns rather than strings
229 (defun rolo-r-not (&rest pat-list)
230 "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements.
231 Each element may be t, nil, or a string."
234 (or (not (setq pat (car pat-list)))
235 (and (not (eq pat t))
237 (not (re-search-forward pat end t)))))
238 (setq pat-list (cdr pat-list)))
239 (if pat-list nil t)))
241 (defun rolo-r-or (&rest pat-list)
242 "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements.
243 Each element may be t, nil, or a string."
244 (if (memq t pat-list)
248 (or (not (setq pat (car pat-list)))
249 (and (not (eq pat t))
251 (not (re-search-forward pat end t)))))
252 (setq pat-list (cdr pat-list)))
253 (if pat-list t nil))))
255 (defun rolo-r-xor (&rest pat-list)
256 "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements.
257 Each element may be t, nil, or a string."
261 (or (not (setq pat (car pat-list)))
263 (not (goto-char start))
264 (re-search-forward pat end t))
265 (setq matches (1+ matches)))
268 (setq pat-list (cdr pat-list)))
271 (defun rolo-r-and (&rest pat-list)
272 "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements.
273 Each element may be t, nil, or a string."
274 (if (memq nil pat-list)
278 (setq pat (car pat-list))
280 (not (goto-char start))
281 (re-search-forward pat end t)))
282 (setq pat-list (cdr pat-list)))
283 (if pat-list nil t))))
285 (provide 'wrolo-logic)
287 ;;; wrolo-logic.el ends here