Mercurial > hg > xemacs-beta
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/hyperbole/wrolo-logic.el Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,277 @@ +;;!emacs +;; +;; FILE: wrolo-logic.el +;; SUMMARY: Performs logical retrievals on rolodex files +;; USAGE: GNU Emacs Lisp Library +;; KEYWORDS: hypermedia, matching +;; +;; AUTHOR: Bob Weiner +;; ORG: Motorola Inc. +;; +;; ORIG-DATE: 13-Jun-89 at 22:57:33 +;; LAST-MOD: 14-Apr-95 at 16:27:43 by Bob Weiner +;; +;; This file is part of Hyperbole. +;; Available for use and distribution under the same terms as GNU Emacs. +;; +;; Copyright (C) 1989-1995, Free Software Foundation, Inc. +;; Developed with support from Motorola Inc. +;; +;; DESCRIPTION: +;; +;; INSTALLATION: +;; +;; See also wrolo.el. These functions are separated from wrolo.el since many +;; users may never want or need them. They can be automatically loaded when +;; desired by adding the following to one of your Emacs init files: +;; +;; (autoload 'rolo-logic "wrolo-logic" "Logical rolodex search filters." t) +;; +;; FEATURES: +;; +;; 1. One command, 'rolo-logic' which takes a logical search expression as +;; an argument and displays any matching entries. +;; +;; 2. Logical 'and', 'or', 'not', and 'xor' rolodex entry retrieval filter +;; functions. They take any number of string or boolean arguments and +;; may be nested. NOTE THAT THESE FUNCTIONS SHOULD NEVER BE CALLED +;; DIRECTLY UNLESS THE FREE VARIABLES 'start' and 'end' ARE BOUND +;; BEFOREHAND. +;; +;; EXAMPLE: +;; +;; (rolo-logic (function +;; (lambda () +;; (rolo-and +;; (rolo-not "Tool-And-Die") +;; "secretary")))) +;; +;; would find all non-Tool-And-Die Corp. secretaries in your rolodex. +;; +;; The logical matching routines are not at all optimal, but then most +;; rolodex files are not terribly lengthy either. +;; +;; DESCRIP-END. + +(require 'wrolo) + +;;;###autoload +(defun rolo-logic (func &optional in-bufs count-only include-sub-entries + no-sub-entries-out) + "Apply FUNC to all entries in optional IN-BUFS, display entries where FUNC is non-nil. +If IN-BUFS is nil, 'rolo-file-list' is used. If optional COUNT-ONLY is +non-nil, don't display entries, return count of matching entries only. If +optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC will be applied across all +sub-entries at once. Default is to apply FUNC to each entry and sub-entry +separately. Entries are displayed with all of their sub-entries unless +INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT flag is non-nil. +FUNC should use the free variables 'start' and 'end' which contain the limits +of the region on which it should operate. Returns number of applications of +FUNC that return non-nil." + (interactive "xLogic function of no arguments, (lambda () (<function calls>): ") + (let ((obuf (current-buffer)) + (display-buf (if count-only + nil + (prog1 (set-buffer (get-buffer-create rolo-display-buffer)) + (setq buffer-read-only nil) + (erase-buffer))))) + (let ((result + (mapcar + (function + (lambda (in-bufs) + (rolo-map-logic func in-bufs count-only include-sub-entries + no-sub-entries-out))) + (cond ((null in-bufs) rolo-file-list) + ((listp in-bufs) in-bufs) + ((list in-bufs)))))) + (let ((total-matches (apply '+ result))) + (if (or count-only (= total-matches 0)) + nil + (pop-to-buffer display-buf) + (goto-char (point-min)) + (set-buffer-modified-p nil) + (setq buffer-read-only t) + (let ((buf (get-buffer-window obuf))) + (if buf (select-window buf) (switch-to-buffer buf)))) + (if (interactive-p) + (message (concat (if (= total-matches 0) "No" total-matches) + " matching entr" + (if (= total-matches 1) "y" "ies") + " found in rolodex."))) + total-matches)))) + +(defun rolo-map-logic (func rolo-buf &optional count-only + include-sub-entries no-sub-entries-out) + "Apply FUNC to all entries in ROLO-BUF, write to buffer entries where FUNC is non-nil. +If optional COUNT-ONLY is non-nil, don't display entries, return count of +matching entries only. If optional INCLUDE-SUB-ENTRIES flag is non-nil, FUNC +will be applied across all sub-entries at once. Default is to apply FUNC to +each entry and sub-entry separately. Entries are displayed with all of their +sub-entries unless INCLUDE-SUB-ENTRIES is nil and optional NO-SUB-ENTRIES-OUT +flag is non-nil. FUNC should use the free variables 'start' and 'end' which +contain the limits of the region on which it should operate. Returns number +of applications of FUNC that return non-nil." + (if (or (bufferp rolo-buf) + (if (file-exists-p rolo-buf) + (setq rolo-buf (find-file-noselect rolo-buf t)))) + (let* ((display-buf (set-buffer (get-buffer-create rolo-display-buffer))) + (buffer-read-only)) + (let ((hdr-pos) (num-found 0)) + (set-buffer rolo-buf) + (goto-char (point-min)) + (if (re-search-forward rolo-hdr-regexp nil t 2) + (progn (forward-line) + (setq hdr-pos (cons (point-min) (point))))) + (let* ((start) + (end) + (end-entry-hdr) + (curr-entry-level)) + (while (re-search-forward rolo-entry-regexp nil t) + (setq start (save-excursion (beginning-of-line) (point)) + next-entry-exists nil + end-entry-hdr (point) + curr-entry-level (buffer-substring start end-entry-hdr) + end (rolo-to-entry-end include-sub-entries curr-entry-level)) + (let ((fun (funcall func))) + (or count-only + (and fun (= num-found 0) hdr-pos + (append-to-buffer display-buf + (car hdr-pos) (cdr hdr-pos)))) + (if fun + (progn (goto-char end) + (setq num-found (1+ num-found) + end (if (or include-sub-entries + no-sub-entries-out) + end + (goto-char (rolo-to-entry-end + t curr-entry-level)))) + (or count-only + (append-to-buffer display-buf start end))) + (goto-char end-entry-hdr))))) + (rolo-kill-buffer rolo-buf) + num-found)) + 0)) + + +;; +;; INTERNAL FUNCTIONS. +;; + +;; Do NOT call the following functions directly. +;; Send them as parts of a lambda expression to 'rolo-logic'. + +(defun rolo-not (&rest pat-list) + "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (let ((pat)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (not (eq pat t)) + (goto-char start) + (not (search-forward pat end t))))) + (setq pat-list (cdr pat-list))) + (if pat-list nil t))) + +(defun rolo-or (&rest pat-list) + "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (if (memq t pat-list) + t + (let ((pat)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (not (eq pat t)) + (goto-char start) + (not (search-forward pat end t))))) + (setq pat-list (cdr pat-list))) + (if pat-list t nil)))) + +(defun rolo-xor (&rest pat-list) + "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (let ((pat) + (matches 0)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (or (eq pat t) + (not (goto-char start)) + (search-forward pat end t)) + (setq matches (1+ matches))) + t) + (< matches 2)) + (setq pat-list (cdr pat-list))) + (= matches 1))) + +(defun rolo-and (&rest pat-list) + "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (if (memq nil pat-list) + nil + (let ((pat)) + (while (and pat-list + (setq pat (car pat-list)) + (or (eq pat t) + (not (goto-char start)) + (search-forward pat end t))) + (setq pat-list (cdr pat-list))) + (if pat-list nil t)))) + +;; Work with regular expression patterns rather than strings + +(defun rolo-r-not (&rest pat-list) + "Logical <not> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (let ((pat)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (not (eq pat t)) + (goto-char start) + (not (re-search-forward pat end t))))) + (setq pat-list (cdr pat-list))) + (if pat-list nil t))) + +(defun rolo-r-or (&rest pat-list) + "Logical <or> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (if (memq t pat-list) + t + (let ((pat)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (not (eq pat t)) + (goto-char start) + (not (re-search-forward pat end t))))) + (setq pat-list (cdr pat-list))) + (if pat-list t nil)))) + +(defun rolo-r-xor (&rest pat-list) + "Logical <xor> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (let ((pat) + (matches 0)) + (while (and pat-list + (or (not (setq pat (car pat-list))) + (and (or (eq pat t) + (not (goto-char start)) + (re-search-forward pat end t)) + (setq matches (1+ matches))) + t) + (< matches 2)) + (setq pat-list (cdr pat-list))) + (= matches 1))) + +(defun rolo-r-and (&rest pat-list) + "Logical <and> rolodex entry filter. PAT-LIST is a list of pattern elements. +Each element may be t, nil, or a string." + (if (memq nil pat-list) + nil + (let ((pat)) + (while (and pat-list + (setq pat (car pat-list)) + (or (eq pat t) + (not (goto-char start)) + (re-search-forward pat end t))) + (setq pat-list (cdr pat-list))) + (if pat-list nil t)))) + +(provide 'wrolo-logic)