Mercurial > hg > xemacs-beta
comparison lisp/hyperbole/wrolo-logic.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;!emacs | |
2 ;; | |
3 ;; FILE: wrolo-logic.el | |
4 ;; SUMMARY: Performs logical retrievals on rolodex files | |
5 ;; USAGE: GNU Emacs Lisp Library | |
6 ;; KEYWORDS: hypermedia, matching | |
7 ;; | |
8 ;; AUTHOR: Bob Weiner | |
9 ;; ORG: Motorola Inc. | |
10 ;; | |
11 ;; ORIG-DATE: 13-Jun-89 at 22:57:33 | |
12 ;; LAST-MOD: 14-Apr-95 at 16:27:43 by Bob Weiner | |
13 ;; | |
14 ;; This file is part of Hyperbole. | |
15 ;; Available for use and distribution under the same terms as GNU Emacs. | |
16 ;; | |
17 ;; Copyright (C) 1989-1995, Free Software Foundation, Inc. | |
18 ;; Developed with support from Motorola Inc. | |
19 ;; | |
20 ;; DESCRIPTION: | |
21 ;; | |
22 ;; INSTALLATION: | |
23 ;; | |
24 ;; See also wrolo.el. These functions are separated from wrolo.el since many | |
25 ;; users may never want or need them. They can be automatically loaded when | |
26 ;; desired by adding the following to one of your Emacs init files: | |
27 ;; | |
28 ;; (autoload 'rolo-logic "wrolo-logic" "Logical rolodex search filters." t) | |
29 ;; | |
30 ;; FEATURES: | |
31 ;; | |
32 ;; 1. One command, 'rolo-logic' which takes a logical search expression as | |
33 ;; an argument and displays any matching entries. | |
34 ;; | |
35 ;; 2. Logical 'and', 'or', 'not', and 'xor' rolodex entry retrieval filter | |
36 ;; functions. They take any number of string or boolean arguments and | |
37 ;; may be nested. NOTE THAT THESE FUNCTIONS SHOULD NEVER BE CALLED | |
38 ;; DIRECTLY UNLESS THE FREE VARIABLES 'start' and 'end' ARE BOUND | |
39 ;; BEFOREHAND. | |
40 ;; | |
41 ;; EXAMPLE: | |
42 ;; | |
43 ;; (rolo-logic (function | |
44 ;; (lambda () | |
45 ;; (rolo-and | |
46 ;; (rolo-not "Tool-And-Die") | |
47 ;; "secretary")))) | |
48 ;; | |
49 ;; would find all non-Tool-And-Die Corp. secretaries in your rolodex. | |
50 ;; | |
51 ;; The logical matching routines are not at all optimal, but then most | |
52 ;; rolodex files are not terribly lengthy either. | |
53 ;; | |
54 ;; DESCRIP-END. | |
55 | |
56 (require 'wrolo) | |
57 | |
58 ;;;###autoload | |
59 (defun rolo-logic (func &optional in-bufs count-only include-sub-entries | |
60 no-sub-entries-out) | |
61 "Apply FUNC to all entries in optional IN-BUFS, display entries where FUNC is non-nil. | |
62 If IN-BUFS is nil, 'rolo-file-list' is used. If optional COUNT-ONLY is | |
63 non-nil, don't display entries, return count of matching entries only. If | |
64 optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC will be applied across all | |
65 sub-entries at once. Default is to apply FUNC to each entry and sub-entry | |
66 separately. Entries are displayed with all of their sub-entries unless | |
67 INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil. | |
68 FUNC should use the free variables 'start' and 'end' which contain the limits | |
69 of the region on which it should operate. Returns number of applications of | |
70 FUNC that return non-nil." | |
71 (interactive "xLogic function of no arguments, (lambda () (<function calls>): ") | |
72 (let ((obuf (current-buffer)) | |
73 (display-buf (if count-only | |
74 nil | |
75 (prog1 (set-buffer (get-buffer-create rolo-display-buffer)) | |
76 (setq buffer-read-only nil) | |
77 (erase-buffer))))) | |
78 (let ((result | |
79 (mapcar | |
80 (function | |
81 (lambda (in-bufs) | |
82 (rolo-map-logic func in-bufs count-only include-sub-entries | |
83 no-sub-entries-out))) | |
84 (cond ((null in-bufs) rolo-file-list) | |
85 ((listp in-bufs) in-bufs) | |
86 ((list in-bufs)))))) | |
87 (let ((total-matches (apply '+ result))) | |
88 (if (or count-only (= total-matches 0)) | |
89 nil | |
90 (pop-to-buffer display-buf) | |
91 (goto-char (point-min)) | |
92 (set-buffer-modified-p nil) | |
93 (setq buffer-read-only t) | |
94 (let ((buf (get-buffer-window obuf))) | |
95 (if buf (select-window buf) (switch-to-buffer buf)))) | |
96 (if (interactive-p) | |
97 (message (concat (if (= total-matches 0) "No" total-matches) | |
98 " matching entr" | |
99 (if (= total-matches 1) "y" "ies") | |
100 " found in rolodex."))) | |
101 total-matches)))) | |
102 | |
103 (defun rolo-map-logic (func rolo-buf &optional count-only | |
104 include-sub-entries no-sub-entries-out) | |
105 "Apply FUNC to all entries in ROLO-BUF, write to buffer entries where FUNC is non-nil. | |
106 If optional COUNT-ONLY is non-nil, don't display entries, return count of | |
107 matching entries only. If optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC | |
108 will be applied across all sub-entries at once. Default is to apply FUNC to | |
109 each entry and sub-entry separately. Entries are displayed with all of their | |
110 sub-entries unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT | |
111 flag is non-nil. FUNC should use the free variables 'start' and 'end' which | |
112 contain the limits of the region on which it should operate. Returns number | |
113 of applications of FUNC that return non-nil." | |
114 (if (or (bufferp rolo-buf) | |
115 (if (file-exists-p rolo-buf) | |
116 (setq rolo-buf (find-file-noselect rolo-buf t)))) | |
117 (let* ((display-buf (set-buffer (get-buffer-create rolo-display-buffer))) | |
118 (buffer-read-only)) | |
119 (let ((hdr-pos) (num-found 0)) | |
120 (set-buffer rolo-buf) | |
121 (goto-char (point-min)) | |
122 (if (re-search-forward rolo-hdr-regexp nil t 2) | |
123 (progn (forward-line) | |
124 (setq hdr-pos (cons (point-min) (point))))) | |
125 (let* ((start) | |
126 (end) | |
127 (end-entry-hdr) | |
128 (curr-entry-level)) | |
129 (while (re-search-forward rolo-entry-regexp nil t) | |
130 (setq start (save-excursion (beginning-of-line) (point)) | |
131 next-entry-exists nil | |
132 end-entry-hdr (point) | |
133 curr-entry-level (buffer-substring start end-entry-hdr) | |
134 end (rolo-to-entry-end include-sub-entries curr-entry-level)) | |
135 (let ((fun (funcall func))) | |
136 (or count-only | |
137 (and fun (= num-found 0) hdr-pos | |
138 (append-to-buffer display-buf | |
139 (car hdr-pos) (cdr hdr-pos)))) | |
140 (if fun | |
141 (progn (goto-char end) | |
142 (setq num-found (1+ num-found) | |
143 end (if (or include-sub-entries | |
144 no-sub-entries-out) | |
145 end | |
146 (goto-char (rolo-to-entry-end | |
147 t curr-entry-level)))) | |
148 (or count-only | |
149 (append-to-buffer display-buf start end))) | |
150 (goto-char end-entry-hdr))))) | |
151 (rolo-kill-buffer rolo-buf) | |
152 num-found)) | |
153 0)) | |
154 | |
155 | |
156 ;; | |
157 ;; INTERNAL FUNCTIONS. | |
158 ;; | |
159 | |
160 ;; Do NOT call the following functions directly. | |
161 ;; Send them as parts of a lambda expression to 'rolo-logic'. | |
162 | |
163 (defun rolo-not (&rest pat-list) | |
164 "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
165 Each element may be t, nil, or a string." | |
166 (let ((pat)) | |
167 (while (and pat-list | |
168 (or (not (setq pat (car pat-list))) | |
169 (and (not (eq pat t)) | |
170 (goto-char start) | |
171 (not (search-forward pat end t))))) | |
172 (setq pat-list (cdr pat-list))) | |
173 (if pat-list nil t))) | |
174 | |
175 (defun rolo-or (&rest pat-list) | |
176 "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
177 Each element may be t, nil, or a string." | |
178 (if (memq t pat-list) | |
179 t | |
180 (let ((pat)) | |
181 (while (and pat-list | |
182 (or (not (setq pat (car pat-list))) | |
183 (and (not (eq pat t)) | |
184 (goto-char start) | |
185 (not (search-forward pat end t))))) | |
186 (setq pat-list (cdr pat-list))) | |
187 (if pat-list t nil)))) | |
188 | |
189 (defun rolo-xor (&rest pat-list) | |
190 "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
191 Each element may be t, nil, or a string." | |
192 (let ((pat) | |
193 (matches 0)) | |
194 (while (and pat-list | |
195 (or (not (setq pat (car pat-list))) | |
196 (and (or (eq pat t) | |
197 (not (goto-char start)) | |
198 (search-forward pat end t)) | |
199 (setq matches (1+ matches))) | |
200 t) | |
201 (< matches 2)) | |
202 (setq pat-list (cdr pat-list))) | |
203 (= matches 1))) | |
204 | |
205 (defun rolo-and (&rest pat-list) | |
206 "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
207 Each element may be t, nil, or a string." | |
208 (if (memq nil pat-list) | |
209 nil | |
210 (let ((pat)) | |
211 (while (and pat-list | |
212 (setq pat (car pat-list)) | |
213 (or (eq pat t) | |
214 (not (goto-char start)) | |
215 (search-forward pat end t))) | |
216 (setq pat-list (cdr pat-list))) | |
217 (if pat-list nil t)))) | |
218 | |
219 ;; Work with regular expression patterns rather than strings | |
220 | |
221 (defun rolo-r-not (&rest pat-list) | |
222 "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
223 Each element may be t, nil, or a string." | |
224 (let ((pat)) | |
225 (while (and pat-list | |
226 (or (not (setq pat (car pat-list))) | |
227 (and (not (eq pat t)) | |
228 (goto-char start) | |
229 (not (re-search-forward pat end t))))) | |
230 (setq pat-list (cdr pat-list))) | |
231 (if pat-list nil t))) | |
232 | |
233 (defun rolo-r-or (&rest pat-list) | |
234 "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
235 Each element may be t, nil, or a string." | |
236 (if (memq t pat-list) | |
237 t | |
238 (let ((pat)) | |
239 (while (and pat-list | |
240 (or (not (setq pat (car pat-list))) | |
241 (and (not (eq pat t)) | |
242 (goto-char start) | |
243 (not (re-search-forward pat end t))))) | |
244 (setq pat-list (cdr pat-list))) | |
245 (if pat-list t nil)))) | |
246 | |
247 (defun rolo-r-xor (&rest pat-list) | |
248 "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
249 Each element may be t, nil, or a string." | |
250 (let ((pat) | |
251 (matches 0)) | |
252 (while (and pat-list | |
253 (or (not (setq pat (car pat-list))) | |
254 (and (or (eq pat t) | |
255 (not (goto-char start)) | |
256 (re-search-forward pat end t)) | |
257 (setq matches (1+ matches))) | |
258 t) | |
259 (< matches 2)) | |
260 (setq pat-list (cdr pat-list))) | |
261 (= matches 1))) | |
262 | |
263 (defun rolo-r-and (&rest pat-list) | |
264 "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements. | |
265 Each element may be t, nil, or a string." | |
266 (if (memq nil pat-list) | |
267 nil | |
268 (let ((pat)) | |
269 (while (and pat-list | |
270 (setq pat (car pat-list)) | |
271 (or (eq pat t) | |
272 (not (goto-char start)) | |
273 (re-search-forward pat end t))) | |
274 (setq pat-list (cdr pat-list))) | |
275 (if pat-list nil t)))) | |
276 | |
277 (provide 'wrolo-logic) |