comparison lisp/hyperbole/wrolo.el @ 114:8619ce7e4c50 r20-1b9

Import from CVS: tag r20-1b9
author cvs
date Mon, 13 Aug 2007 09:21:54 +0200
parents 4be1180a9e89
children
comparison
equal deleted inserted replaced
113:2ec2fe4a4c89 114:8619ce7e4c50
13 ;; contracts for InfoDock, Emacs and XEmacs. 13 ;; contracts for InfoDock, Emacs and XEmacs.
14 ;; E-mail: <info@infodock.com> Web: http://www.infodock.com 14 ;; E-mail: <info@infodock.com> Web: http://www.infodock.com
15 ;; Tel: +1 408-243-3300 15 ;; Tel: +1 408-243-3300
16 ;; 16 ;;
17 ;; ORIG-DATE: 7-Jun-89 at 22:08:29 17 ;; ORIG-DATE: 7-Jun-89 at 22:08:29
18 ;; LAST-MOD: 17-Feb-97 at 15:32:20 by Bob Weiner 18 ;; LAST-MOD: 14-Mar-97 at 01:32:23 by Bob Weiner
19 ;; 19 ;;
20 ;; This file is part of Hyperbole. 20 ;; This file is part of Hyperbole.
21 ;; Available for use and distribution under the same terms as GNU Emacs. 21 ;; Available for use and distribution under the same terms as GNU Emacs.
22 ;; 22 ;;
23 ;; Copyright (C) 1989, '90, '91, '92, '95 Free Software Foundation, Inc. 23 ;; Copyright (C) 1989, '90, '91, '92, '95, '96, '97 Free Software Foundation, Inc.
24 ;; Copyright (C) 1996 InfoDock Associates
25 ;; 24 ;;
26 ;; DESCRIPTION: 25 ;; DESCRIPTION:
27 ;; 26 ;;
28 ;; The `put whatever you feel like into it' rolodex. 27 ;; The `put whatever you feel like into it' rolodex.
29 ;; 28 ;;
61 ;; wrolo as part of Hyperbole, this file in unneeded and so not included.) 60 ;; wrolo as part of Hyperbole, this file in unneeded and so not included.)
62 ;; 61 ;;
63 ;; 62 ;;
64 ;; SETUP: 63 ;; SETUP:
65 ;; 64 ;;
66 ;; The variable 'rolo-file-list' is a list of files to search for 65 ;; The variable `rolo-file-list' is a list of files to search for
67 ;; matching rolodex entries. To add personal files to rolo-file-list, 66 ;; matching rolodex entries. To add personal files to rolo-file-list,
68 ;; when you find these functions are useful for any sort of list lookup, 67 ;; when you find these functions are useful for any sort of list lookup,
69 ;; add the following to your ~/.emacs file (substituting where you see 68 ;; add the following to your ~/.emacs file (substituting where you see
70 ;; <fileN>): 69 ;; <fileN>):
71 ;; 70 ;;
72 ;; (setq rolo-file-list (append rolo-file-list '("<file1>" "<file2>"))) 71 ;; (setq rolo-file-list (append rolo-file-list '("<file1>" "<file2>")))
73 ;; 72 ;;
74 ;; We recommend that entries in 'rolo-file-list' have ".otl" suffixes 73 ;; We recommend that entries in `rolo-file-list' have ".otl" suffixes
75 ;; so that they do not conflict with file names that other rolodex 74 ;; so that they do not conflict with file names that other rolodex
76 ;; programs might use and so that they are edited in 'outline-mode' by 75 ;; programs might use and so that they are edited in `outline-mode' by
77 ;; default. If you want the latter behavior, uncomment and add something 76 ;; default. If you want the latter behavior, uncomment and add something
78 ;; like the following to one of your GNU Emacs initialization files: 77 ;; like the following to one of your GNU Emacs initialization files:
79 ;; 78 ;;
80 ;; ;; Add to the list of suffixes that causes automatic mode invocation 79 ;; ;; Add to the list of suffixes that causes automatic mode invocation
81 ;; (setq auto-mode-alist 80 ;; (setq auto-mode-alist
96 ;; 95 ;;
97 ;; When adding an entry from within a buffer containing a mail 96 ;; When adding an entry from within a buffer containing a mail
98 ;; message, the rolodex add function will extract the sender's name 97 ;; message, the rolodex add function will extract the sender's name
99 ;; and e-mail address and prompt you with the name as a default. If 98 ;; and e-mail address and prompt you with the name as a default. If
100 ;; you accept it, it will enter the name and the email address using 99 ;; you accept it, it will enter the name and the email address using
101 ;; the format given by the 'rolo-email-format' variable. See its 100 ;; the format given by the `rolo-email-format' variable. See its
102 ;; documentation if you want to change its value. 101 ;; documentation if you want to change its value.
103 ;; 102 ;;
104 ;; 103 ;;
105 ;; If you use Hyperbole V2.3 or greater, then no other rolodex setup 104 ;; If you use Hyperbole V2.3 or greater, then no other rolodex setup
106 ;; is necessary, simply select the "Rolo/" menu item from the top 105 ;; is necessary, simply select the "Rolo/" menu item from the top
137 ;; 136 ;;
138 ;; For any of these commands that prompt you for a name, you may use the form 137 ;; For any of these commands that prompt you for a name, you may use the form
139 ;; parent/child to locate a child entry below a parent entry, e.g. 138 ;; parent/child to locate a child entry below a parent entry, e.g.
140 ;; from the example near the top, we could give Company/Manager/Underlings. 139 ;; from the example near the top, we could give Company/Manager/Underlings.
141 ;; 140 ;;
142 ;; Here is a snippet from our group rolodex file. The ';'s should be 141 ;; Here is a snippet from our group rolodex file. The `;'s should be
143 ;; removed of course and the '*'s should begin at the start of the 142 ;; removed of course and the `*'s should begin at the start of the
144 ;; line. If a rolodex file begins with two separator lines whose 143 ;; line. If a rolodex file begins with two separator lines whose
145 ;; first three characters are "===", then these lines and any text 144 ;; first three characters are "===", then these lines and any text
146 ;; between them are prepended to the output buffer whenever any 145 ;; between them are prepended to the output buffer whenever any
147 ;; entries are retrieved from that file. 146 ;; entries are retrieved from that file.
148 ;; 147 ;;
158 ;; 157 ;;
159 ;; 158 ;;
160 ;; FOR PROGRAMMERS: 159 ;; FOR PROGRAMMERS:
161 ;; 160 ;;
162 ;; Entries in rolodex files are separated by patterns matching 161 ;; Entries in rolodex files are separated by patterns matching
163 ;; 'rolo-entry-regexp'. Each entry may have any number of sub-entries 162 ;; `rolo-entry-regexp'. Each entry may have any number of sub-entries
164 ;; which represent the next level down in the entry hierarchy. 163 ;; which represent the next level down in the entry hierarchy.
165 ;; Sub-entries' separator patterns are always longer than their parents'. 164 ;; Sub-entries' separator patterns are always longer than their parents'.
166 ;; For example, if an entry began with '*' then its sub-entries would begin 165 ;; For example, if an entry began with `*' then its sub-entries would begin
167 ;; with '**' and so on. Blank lines in rolodex files will not end up where 166 ;; with `**' and so on. Blank lines in rolodex files will not end up where
168 ;; you want them if you use the rolo-sort commands; therefore, blank lines 167 ;; you want them if you use the rolo-sort commands; therefore, blank lines
169 ;; are not recommended. If you change the value of 168 ;; are not recommended. If you change the value of
170 ;; 'rolo-entry-regexp', you will have to modify 'rolo-sort'. 169 ;; `rolo-entry-regexp', you will have to modify `rolo-sort'.
171 ;; 170 ;;
172 ;; The following additional functions are provided: 171 ;; The following additional functions are provided:
173 ;; 172 ;;
174 ;; 'rolo-sort-level' sorts a specific level of entries in a rolodex file; 173 ;; `rolo-sort-level' sorts a specific level of entries in a rolodex file;
175 ;; 'rolo-map-level' runs a user specified function on a specific level of 174 ;; `rolo-map-level' runs a user specified function on a specific level of
176 ;; entries in a rolodex file; 175 ;; entries in a rolodex file;
177 ;; 'rolo-fgrep-file', same as 'rolo-fgrep' but operates on a single file; 176 ;; `rolo-fgrep-file', same as `rolo-fgrep' but operates on a single file;
178 ;; 'rolo-grep-file', same as 'rolo-grep' but operates on a single file; 177 ;; `rolo-grep-file', same as `rolo-grep' but operates on a single file;
179 ;; 'rolo-display-matches', display last set of rolodex matches, if any; 178 ;; `rolo-display-matches', display last set of rolodex matches, if any;
180 ;; 'rolo-toggle-narrow-to-entry' toggles between display of current entry 179 ;; `rolo-toggle-narrow-to-entry' toggles between display of current entry
181 ;; and display of all matching entries. 180 ;; and display of all matching entries.
182 ;; 181 ;;
183 ;; 182 ;;
184 ;; MOD HISTORY: 183 ;; MOD HISTORY:
185 ;; 184 ;;
186 ;; 12/17/89 185 ;; 12/17/89
187 ;; Added internal 'rolo-shrink-window' function for use in 186 ;; Added internal `rolo-shrink-window' function for use in
188 ;; compressing/uncompressing the rolo view window to/from a size just 187 ;; compressing/uncompressing the rolo view window to/from a size just
189 ;; large enough for the selected entry. This is useful when a search 188 ;; large enough for the selected entry. This is useful when a search
190 ;; turns up more entries than desired. 189 ;; turns up more entries than desired.
191 ;; 190 ;;
192 ;; 02/21/90 191 ;; 02/21/90
193 ;; Modified 'rolo-grep-file' and 'rolo-map-level' so they only set buffers 192 ;; Modified `rolo-grep-file' and `rolo-map-level' so they only set buffers
194 ;; read-only the first time they are read in. This way, if someone edits a 193 ;; read-only the first time they are read in. This way, if someone edits a
195 ;; rolodex file and then does a rolo-fgrep or other function, the buffer 194 ;; rolodex file and then does a rolo-fgrep or other function, the buffer
196 ;; will not be back in read-only mode. 195 ;; will not be back in read-only mode.
197 ;; 196 ;;
198 ;; 04/18/91 197 ;; 04/18/91
199 ;; Modified 'rolo-grep-file' to expand any hidden entries in rolo file 198 ;; Modified `rolo-grep-file' to expand any hidden entries in rolo file
200 ;; before doing a search. 199 ;; before doing a search.
201 ;; 200 ;;
202 ;; 12/24/91 201 ;; 12/24/91
203 ;; Added Hyperbole button support. 202 ;; Added Hyperbole button support.
204 ;; 203 ;;
258 "*Non-nil means kill rolodex file buffers after searching them for entries. 257 "*Non-nil means kill rolodex file buffers after searching them for entries.
259 Only unmodified buffers are killed.") 258 Only unmodified buffers are killed.")
260 259
261 (defvar rolo-save-buffers-after-use t 260 (defvar rolo-save-buffers-after-use t
262 "*Non-nil means save rolodex file after an entry is killed.") 261 "*Non-nil means save rolodex file after an entry is killed.")
262
263 ;; Insert or update the entry date each time an entry is added or edited.
264 (add-hook 'wrolo-add-hook 'rolo-set-date)
265 (add-hook 'wrolo-edit-hook 'rolo-set-date)
263 266
264 (defvar wrolo-yank-reformat-function nil 267 (defvar wrolo-yank-reformat-function nil
265 "*Value is a function of two arguments, START and END, invoked after a rolo-yank. 268 "*Value is a function of two arguments, START and END, invoked after a rolo-yank.
266 It should reformat the region given by the arguments to some preferred style. 269 It should reformat the region given by the arguments to some preferred style.
267 Default value is nil, meaning no reformmating is done.") 270 Default value is nil, meaning no reformmating is done.")
288 (list (if (and email name 291 (list (if (and email name
289 (string-match (concat "\\`" (regexp-quote entry)) name)) 292 (string-match (concat "\\`" (regexp-quote entry)) name))
290 (format rolo-email-format entry email) entry) 293 (format rolo-email-format entry email) entry)
291 current-prefix-arg)))) 294 current-prefix-arg))))
292 (if (or (not (stringp name)) (string= name "")) 295 (if (or (not (stringp name)) (string= name ""))
293 (error "(rolo-add): Invalid name: '%s'" name)) 296 (error "(rolo-add): Invalid name: `%s'" name))
294 (if (and (interactive-p) file) 297 (if (and (interactive-p) file)
295 (setq file (completing-read "File to add to: " 298 (setq file (completing-read "File to add to: "
296 (mapcar 'list rolo-file-list)))) 299 (mapcar 'list rolo-file-list))))
297 (if (null file) (setq file (car rolo-file-list))) 300 (if (null file) (setq file (car rolo-file-list)))
298 (cond ((and file (or (not (stringp file)) (string= file ""))) 301 (cond ((and file (or (not (stringp file)) (string= file "")))
299 (error "(rolo-add): Invalid file: '%s'" file)) 302 (error "(rolo-add): Invalid file: `%s'" file))
300 ((and (file-exists-p file) (not (file-readable-p file))) 303 ((and (file-exists-p file) (not (file-readable-p file)))
301 (error "(rolo-add): File not readable: '%s'" file)) 304 (error "(rolo-add): File not readable: `%s'" file))
302 ((not (file-writable-p file)) 305 ((not (file-writable-p file))
303 (error "(rolo-add): File not writable: '%s'" file))) 306 (error "(rolo-add): File not writable: `%s'" file)))
304 (set-buffer (or (get-file-buffer file) (find-file-noselect file))) 307 (set-buffer (or (get-file-buffer file) (find-file-noselect file)))
305 (if (interactive-p) (message "Locating insertion point for '%s'..." name)) 308 (if (interactive-p) (message "Locating insertion point for `%s'..." name))
306 (let ((parent "") (level "") end) 309 (let ((parent "") (level "") end)
307 (widen) (goto-char 1) 310 (widen) (goto-char 1)
308 (while (setq end (string-match "/" name)) 311 (while (setq end (string-match "/" name))
309 (setq parent (substring name 0 end) 312 (setq parent (substring name 0 end)
310 name (substring name (min (1+ end) (length name)))) 313 name (substring name (min (1+ end) (length name))))
311 (if (re-search-forward 314 (if (re-search-forward
312 (concat "\\(" rolo-entry-regexp "\\)[ \t]*" 315 (concat "\\(" rolo-entry-regexp "\\)[ \t]*"
313 (regexp-quote parent)) nil t) 316 (regexp-quote parent)) nil t)
314 (setq level (buffer-substring (match-beginning 1) 317 (setq level (buffer-substring (match-beginning 1)
315 (match-end 1))) 318 (match-end 1)))
316 (error "(rolo-add): '%s' category not found in \"%s\"." 319 (error "(rolo-add): `%s' category not found in \"%s\"."
317 parent file))) 320 parent file)))
318 (narrow-to-region (point) 321 (narrow-to-region (point)
319 (progn (rolo-to-entry-end t level) (point))) 322 (progn (rolo-to-entry-end t level) (point)))
320 (goto-char (point-min)) 323 (goto-char (point-min))
321 (let* ((len (length name)) 324 (let* ((len (length name))
354 ;; restore it. 357 ;; restore it.
355 (let ((opoint (point))) 358 (let ((opoint (point)))
356 (widen) 359 (widen)
357 (rolo-to-buffer (current-buffer)) 360 (rolo-to-buffer (current-buffer))
358 (goto-char opoint)) 361 (goto-char opoint))
362 (run-hooks 'wrolo-add-hook)
359 (if (interactive-p) 363 (if (interactive-p)
360 (message "Edit entry at point."))))) 364 (message "Edit entry at point.")))))
361 365
362 ;;;###autoload 366 ;;;###autoload
363 (defun rolo-display-matches (&optional display-buf return-to-buffer) 367 (defun rolo-display-matches (&optional display-buf return-to-buffer)
364 "Display optional DISPLAY-BUF buffer of previously found rolodex matches. 368 "Display optional DISPLAY-BUF buffer of previously found rolodex matches.
365 If DISPLAY-BUF is nil, use the value in 'rolo-display-buffer'. 369 If DISPLAY-BUF is nil, use the value in `rolo-display-buffer'.
366 Second arg RETURN-TO-BUFFER is the buffer to leave point within after the display." 370 Second arg RETURN-TO-BUFFER is the buffer to leave point within after the display."
367 (interactive) 371 (interactive)
368 (or display-buf (setq display-buf (get-buffer rolo-display-buffer))) 372 (or display-buf (setq display-buf (get-buffer rolo-display-buffer)))
369 (if display-buf nil 373 (if display-buf nil
370 (error "(rolo-display-matches): Search the rolodex first.")) 374 (error "(rolo-display-matches): Search the rolodex first."))
389 ;; been specified. Use {q} to quit and restore display. 393 ;; been specified. Use {q} to quit and restore display.
390 (if return-to-buffer (rolo-to-buffer return-to-buffer t))) 394 (if return-to-buffer (rolo-to-buffer return-to-buffer t)))
391 395
392 ;;;###autoload 396 ;;;###autoload
393 (defun rolo-edit (&optional name file) 397 (defun rolo-edit (&optional name file)
394 "Edits a rolodex entry given by optional NAME within 'rolo-file-list'. 398 "Edits a rolodex entry given by optional NAME within `rolo-file-list'.
395 With prefix argument, prompts for optional FILE to locate entry within. 399 With prefix argument, prompts for optional FILE to locate entry within.
396 With no NAME arg, simply displays FILE or first entry in 'rolo-file-list' in an 400 With no NAME arg, simply displays FILE or first entry in `rolo-file-list' in an
397 editable mode. NAME may be of the form: parent/child to edit child below a 401 editable mode. NAME may be of the form: parent/child to edit child below a
398 parent entry which begins with the parent string." 402 parent entry which begins with the parent string."
399 (interactive "sName to edit in rolo: \nP") 403 (interactive "sName to edit in rolo: \nP")
400 (if (string-equal name "") (setq name nil)) 404 (if (string-equal name "") (setq name nil))
401 (and name (not (stringp name)) 405 (and name (not (stringp name))
402 (error "(rolo-edit): Invalid name: '%s'" name)) 406 (error "(rolo-edit): Invalid name: `%s'" name))
403 (if (and (interactive-p) current-prefix-arg) 407 (if (and (interactive-p) current-prefix-arg)
404 (if (= (length rolo-file-list) 1) 408 (if (= (length rolo-file-list) 1)
405 (setq file (car rolo-file-list)) 409 (setq file (car rolo-file-list))
406 (setq file (completing-read "Entry's File: " 410 (setq file (completing-read "Entry's File: "
407 (mapcar 'list rolo-file-list))))) 411 (mapcar 'list rolo-file-list)))))
408 (let ((found-point) (file-list (if file (list file) rolo-file-list))) 412 (let ((found-point) (file-list (if file (list file) rolo-file-list)))
409 (or file (setq file (car file-list))) 413 (or file (setq file (car file-list)))
410 (if (null name) 414 (if (null name)
411 (progn (if (not (file-writable-p file)) 415 (progn (if (not (file-writable-p file))
412 (error "(rolo-edit): File not writable: '%s'" file)) 416 (error "(rolo-edit): File not writable: `%s'" file))
413 (find-file-other-window file) (setq buffer-read-only nil)) 417 (find-file-other-window file) (setq buffer-read-only nil))
414 (if (setq found-point (rolo-to name file-list)) 418 (if (setq found-point (rolo-to name file-list))
415 (progn 419 (progn
416 (setq file buffer-file-name) 420 (setq file buffer-file-name)
417 (if (file-writable-p file) 421 (if (file-writable-p file)
418 (setq buffer-read-only nil) 422 (setq buffer-read-only nil)
419 (message 423 (message
420 "(rolo-edit): Entry found but file not writable: '%s'" file) 424 "(rolo-edit): Entry found but file not writable: `%s'" file)
421 (beep)) 425 (beep))
422 (rolo-to-buffer (current-buffer))) 426 (rolo-to-buffer (current-buffer)))
423 (message "(rolo-edit): '%s' not found." name) 427 (message "(rolo-edit): `%s' not found." name)
424 (beep) 428 (beep)
425 (rolo-to-buffer (or (get-file-buffer (car file-list)) 429 (rolo-to-buffer (or (get-file-buffer (car file-list))
426 (find-file-noselect (car file-list)))) 430 (find-file-noselect (car file-list))))
427 (setq buffer-read-only nil)) 431 (setq buffer-read-only nil))
428 (widen) 432 (widen)
429 ;; Rolo-to-buffer may have moved point from its desired location, so 433 ;; Rolo-to-buffer may have moved point from its desired location, so
430 ;; restore it. 434 ;; restore it.
431 (if found-point (goto-char found-point))))) 435 (if found-point (goto-char found-point))
436 (run-hooks 'wrolo-edit-hook))))
432 437
433 (defun rolo-edit-entry () 438 (defun rolo-edit-entry ()
434 "Edit the source entry of the rolodex match buffer entry at point. 439 "Edit the source entry of the rolodex match buffer entry at point.
435 Returns entry name if found, else nil." 440 Returns entry name if found, else nil."
436 (interactive) 441 (interactive)
524 (error "(rolo-isearch): Use this command in the %s match buffer" 529 (error "(rolo-isearch): Use this command in the %s match buffer"
525 rolo-display-buffer))) 530 rolo-display-buffer)))
526 531
527 ;;;###autoload 532 ;;;###autoload
528 (defun rolo-kill (name &optional file) 533 (defun rolo-kill (name &optional file)
529 "Kills a rolodex entry given by NAME within 'rolo-file-list'. 534 "Kills a rolodex entry given by NAME within `rolo-file-list'.
530 With prefix argument, prompts for optional FILE to locate entry within. 535 With prefix argument, prompts for optional FILE to locate entry within.
531 NAME may be of the form: parent/child to kill child below a parent entry 536 NAME may be of the form: parent/child to kill child below a parent entry
532 which begins with the parent string. 537 which begins with the parent string.
533 Returns t if entry is killed, nil otherwise." 538 Returns t if entry is killed, nil otherwise."
534 (interactive "sName to kill in rolo: \nP") 539 (interactive "sName to kill in rolo: \nP")
535 (if (or (not (stringp name)) (string= name "")) 540 (if (or (not (stringp name)) (string= name ""))
536 (error "(rolo-kill): Invalid name: '%s'" name)) 541 (error "(rolo-kill): Invalid name: `%s'" name))
537 (if (and (interactive-p) current-prefix-arg) 542 (if (and (interactive-p) current-prefix-arg)
538 (setq file (completing-read "Entry's File: " 543 (setq file (completing-read "Entry's File: "
539 (mapcar 'list rolo-file-list)))) 544 (mapcar 'list rolo-file-list))))
540 (let ((file-list (if file (list file) rolo-file-list)) 545 (let ((file-list (if file (list file) rolo-file-list))
541 (killed)) 546 (killed))
570 (funcall kill-op start level) 575 (funcall kill-op start level)
571 (message "Killed")) 576 (message "Killed"))
572 (message "Aborted"))) 577 (message "Aborted")))
573 (funcall kill-op start level))) 578 (funcall kill-op start level)))
574 (message 579 (message
575 "(rolo-kill): Entry found but file not writable: '%s'" file) 580 "(rolo-kill): Entry found but file not writable: `%s'" file)
576 (beep))) 581 (beep)))
577 (message "(rolo-kill): '%s' not found." name) 582 (message "(rolo-kill): `%s' not found." name)
578 (beep)) 583 (beep))
579 killed)) 584 killed))
580 585
581 (defun rolo-mail-to () 586 (defun rolo-mail-to ()
582 "Start composing mail addressed to the first e-mail address at or after point." 587 "Start composing mail addressed to the first e-mail address at or after point."
628 (set-window-configuration *rolo-wconfig*))) 633 (set-window-configuration *rolo-wconfig*)))
629 634
630 ;;;###autoload 635 ;;;###autoload
631 (defun rolo-sort (&optional rolo-file) 636 (defun rolo-sort (&optional rolo-file)
632 "Sorts up to 14 levels of entries in ROLO-FILE (default is personal rolo). 637 "Sorts up to 14 levels of entries in ROLO-FILE (default is personal rolo).
633 Assumes entries are delimited by one or more '*'characters. 638 Assumes entries are delimited by one or more `*'characters.
634 Returns list of number of groupings at each entry level." 639 Returns list of number of groupings at each entry level."
635 (interactive 640 (interactive
636 (list (let ((default "") 641 (list (let ((default "")
637 (file)) 642 (file))
638 (setq file 643 (setq file
680 (function (lambda (start end) (sort-lines nil start end))) 685 (function (lambda (start end) (sort-lines nil start end)))
681 rolo-file 686 rolo-file
682 level-regexp 687 level-regexp
683 max-groupings))) 688 max-groupings)))
684 689
690 ;;;###autoload
691 (defun rolo-toggle-datestamps (&optional arg)
692 "Toggle whether datestamps are updated when rolodex entries are modified.
693 With optional ARG, turn them on iff ARG is positive."
694 (interactive "P")
695 (if (or (and arg (<= (prefix-numeric-value arg) 0))
696 (and (not (and arg (> (prefix-numeric-value arg) 0)))
697 (boundp 'wrolo-add-hook) (listp wrolo-add-hook)
698 (memq 'rolo-set-date wrolo-add-hook)))
699 (progn (remove-hook 'wrolo-add-hook 'rolo-set-date)
700 (remove-hook 'wrolo-edit-hook 'rolo-set-date)
701 (message "Rolodex date stamps are now turned off."))
702 (add-hook 'wrolo-add-hook 'rolo-set-date)
703 (add-hook 'wrolo-edit-hook 'rolo-set-date)
704 (message "Rolodex date stamps are now turned on.")))
705
685 (defun rolo-toggle-narrow-to-entry () 706 (defun rolo-toggle-narrow-to-entry ()
686 "Toggle between display of current entry and display of all matched entries. 707 "Toggle between display of current entry and display of all matched entries.
687 Useful when bound to a mouse key." 708 Useful when bound to a mouse key."
688 (interactive) 709 (interactive)
689 (if (rolo-narrowed-p) 710 (if (rolo-narrowed-p)
781 (save-excursion 802 (save-excursion
782 (save-restriction 803 (save-restriction
783 (widen) 804 (widen)
784 (goto-char 1) 805 (goto-char 1)
785 ;; Ensure no entries in outline mode are hidden. 806 ;; Ensure no entries in outline mode are hidden.
786 ;; Uses 'show-all' function from outline.el. 807 ;; Uses `show-all' function from outline.el.
787 (and (search-forward "\C-m" nil t) 808 (and (search-forward "\C-m" nil t)
788 (show-all)) 809 (show-all))
789 (if (re-search-forward rolo-hdr-regexp nil t 2) 810 (if (re-search-forward rolo-hdr-regexp nil t 2)
790 (progn (forward-line) 811 (progn (forward-line)
791 (setq hdr-pos (cons (point-min) (point))))) 812 (setq hdr-pos (cons (point-min) (point)))))
844 (let ((num-found 0) 865 (let ((num-found 0)
845 (exact-level-regexp (concat "^\\(" level-regexp "\\)[ \t\n]")) 866 (exact-level-regexp (concat "^\\(" level-regexp "\\)[ \t\n]"))
846 (outline-regexp rolo-entry-regexp) 867 (outline-regexp rolo-entry-regexp)
847 (buffer-read-only) 868 (buffer-read-only)
848 (level-len)) 869 (level-len))
849 ;; Load 'outline' library since its functions are used here. 870 ;; Load `outline' library since its functions are used here.
850 (if (not (boundp 'outline-mode-map)) 871 (if (not (boundp 'outline-mode-map))
851 (load-library "outline")) 872 (load-library "outline"))
852 (goto-char (point-min)) 873 (goto-char (point-min))
853 ;; Pass buffer header if it exists 874 ;; Pass buffer header if it exists
854 (if (re-search-forward rolo-hdr-regexp nil t 2) 875 (if (re-search-forward rolo-hdr-regexp nil t 2)
888 end 909 end
889 (if (re-search-forward 910 (if (re-search-forward
890 rolo-entry-regexp nil t) 911 rolo-entry-regexp nil t)
891 (progn (beginning-of-line) (point)) 912 (progn (beginning-of-line) (point))
892 (point-max)))) 913 (point-max))))
893 ;; Remember last expression in 'progn' 914 ;; Remember last expression in `progn'
894 ;; must always return non-nil. 915 ;; must always return non-nil.
895 (goto-char start))) 916 (goto-char start)))
896 (not grouping-end))) 917 (not grouping-end)))
897 (let ((end (point))) 918 (let ((end (point)))
898 (goto-char grouping-start) 919 (goto-char grouping-start)
923 (car (memq (get-buffer (or (and (stringp rolo-buf) 944 (car (memq (get-buffer (or (and (stringp rolo-buf)
924 (get-file-buffer rolo-buf)) 945 (get-file-buffer rolo-buf))
925 rolo-buf)) 946 rolo-buf))
926 (buffer-list)))) 947 (buffer-list))))
927 948
949 (defun rolo-current-date ()
950 "Return the current date (a string) in a form used for rolodex entry insertion."
951 (let ((year-month-day (htz:date-parse (current-time-string))))
952 (format "\t%02s/%02s/%s"
953 (aref year-month-day 1)
954 (aref year-month-day 2)
955 (aref year-month-day 0))))
956
928 (defun rolo-display-to-entry-end () 957 (defun rolo-display-to-entry-end ()
929 "Go to end of current entry, ignoring sub-entries." 958 "Go to end of current entry, ignoring sub-entries."
930 (if (re-search-forward (concat rolo-hdr-regexp "\\|" 959 (if (re-search-forward (concat rolo-hdr-regexp "\\|"
931 rolo-entry-regexp) nil t) 960 rolo-entry-regexp) nil t)
932 (progn (beginning-of-line) (point)) 961 (progn (beginning-of-line) (point))
950 (hproperty:but-add (match-beginning 0) (match-end 0) 979 (hproperty:but-add (match-beginning 0) (match-end 0)
951 (or rolo-highlight-face 980 (or rolo-highlight-face
952 hproperty:highlight-face))))))) 981 hproperty:highlight-face)))))))
953 982
954 (defun rolo-kill-buffer (&optional rolo-buf) 983 (defun rolo-kill-buffer (&optional rolo-buf)
955 "Kills optional ROLO-BUF if unchanged and 'rolo-kill-buffers-after-use' is t. 984 "Kills optional ROLO-BUF if unchanged and `rolo-kill-buffers-after-use' is t.
956 Default is current buffer." 985 Default is current buffer."
957 (or rolo-buf (setq rolo-buf (current-buffer))) 986 (or rolo-buf (setq rolo-buf (current-buffer)))
958 (and rolo-kill-buffers-after-use (not (buffer-modified-p rolo-buf)) 987 (and rolo-kill-buffers-after-use (not (buffer-modified-p rolo-buf))
959 (kill-buffer rolo-buf))) 988 (kill-buffer rolo-buf)))
960 989
961 (defun rolo-name-and-email () 990 (defun rolo-name-and-email ()
962 "If point is in a mail message, returns list of (name email-addr) of sender. 991 "If point is in a mail message, returns list of (name email-addr) of sender.
963 Name is returned as 'last, first-and-middle'." 992 Name is returned as `last, first-and-middle'."
964 (let ((email) (name) (from)) 993 (let ((email) (name) (from))
965 (save-window-excursion 994 (save-window-excursion
966 (if (or (hmail:lister-p) (hnews:lister-p)) 995 (if (or (hmail:lister-p) (hnews:lister-p))
967 (other-window 1)) 996 (other-window 1))
968 (save-excursion 997 (save-excursion
994 (match-end 4))))))) 1023 (match-end 4)))))))
995 (if (or name email) 1024 (if (or name email)
996 (list name email)))) 1025 (list name email))))
997 1026
998 (defun rolo-name-at () 1027 (defun rolo-name-at ()
999 "If point is within an entry in 'rolo-display-buffer', returns entry, else nil." 1028 "If point is within an entry in `rolo-display-buffer', returns entry, else nil."
1000 (if (string-equal (buffer-name) rolo-display-buffer) 1029 (if (string-equal (buffer-name) rolo-display-buffer)
1001 (save-excursion 1030 (save-excursion
1002 (if (or (looking-at rolo-entry-regexp) 1031 (if (or (looking-at rolo-entry-regexp)
1003 (progn (end-of-line) 1032 (progn (end-of-line)
1004 (re-search-backward rolo-entry-regexp nil t))) 1033 (re-search-backward rolo-entry-regexp nil t)))
1011 1040
1012 (defun rolo-narrowed-p () 1041 (defun rolo-narrowed-p ()
1013 (or (/= (point-min) 1) (/= (1+ (buffer-size)) (point-max)))) 1042 (or (/= (point-min) 1) (/= (1+ (buffer-size)) (point-max))))
1014 1043
1015 (defun rolo-save-buffer (&optional rolo-buf) 1044 (defun rolo-save-buffer (&optional rolo-buf)
1016 "Saves optional ROLO-BUF if changed and 'rolo-save-buffers-after-use' is t. 1045 "Saves optional ROLO-BUF if changed and `rolo-save-buffers-after-use' is t.
1017 Default is current buffer. Used, for example, after a rolo entry is killed." 1046 Default is current buffer. Used, for example, after a rolo entry is killed."
1018 (or rolo-buf (setq rolo-buf (current-buffer))) 1047 (or rolo-buf (setq rolo-buf (current-buffer)))
1019 (and rolo-save-buffers-after-use (buffer-modified-p rolo-buf) 1048 (and rolo-save-buffers-after-use (buffer-modified-p rolo-buf)
1020 (set-buffer rolo-buf) (save-buffer))) 1049 (set-buffer rolo-buf) (save-buffer)))
1050
1051 (defun rolo-set-date ()
1052 "Add a line with the current date at the end of the current rolodex entry.
1053 Suitable for use as an entry in `wrolo-add-hook' and `wrolo-edit-hook'.
1054 The default date format is MM/DD/YYYY. Rewrite `rolo-current-date' to
1055 return a different format, if you prefer."
1056 (save-excursion
1057 (skip-chars-forward "*")
1058 (rolo-to-entry-end)
1059 (skip-chars-backward " \t\n\r\f")
1060 (skip-chars-backward "^\n\r\f")
1061 (if (looking-at "\\s-+[-0-9./]+\\s-*$") ;; a date
1062 (progn (delete-region (point) (match-end 0))
1063 (insert (rolo-current-date)))
1064 (end-of-line)
1065 (insert "\n" (rolo-current-date)))))
1021 1066
1022 (defun rolo-shrink-window () 1067 (defun rolo-shrink-window ()
1023 (let* ((lines (count-lines (point-min) (point-max))) 1068 (let* ((lines (count-lines (point-min) (point-max)))
1024 (height (window-height)) 1069 (height (window-height))
1025 (window-min-height 2) 1070 (window-min-height 2)
1032 (max desired-shrinkage (- height (/ (frame-height) 2))) 1077 (max desired-shrinkage (- height (/ (frame-height) 2)))
1033 (min desired-shrinkage (- height window-min-height))))))) 1078 (min desired-shrinkage (- height window-min-height)))))))
1034 1079
1035 (defun rolo-to (name &optional file-list) 1080 (defun rolo-to (name &optional file-list)
1036 "Moves point to entry for NAME within optional FILE-LIST. 1081 "Moves point to entry for NAME within optional FILE-LIST.
1037 'rolo-file-list' is used as default when FILE-LIST is nil. 1082 `rolo-file-list' is used as default when FILE-LIST is nil.
1038 Leaves point immediately after match for NAME within entry. 1083 Leaves point immediately after match for NAME within entry.
1039 Switches internal current buffer but does not alter the frame. 1084 Switches internal current buffer but does not alter the frame.
1040 Returns point where matching entry begins or nil if not found." 1085 Returns point where matching entry begins or nil if not found."
1041 (or file-list (setq file-list rolo-file-list)) 1086 (or file-list (setq file-list rolo-file-list))
1042 (let ((found) file) 1087 (let ((found) file)
1043 (while (and (not found) file-list) 1088 (while (and (not found) file-list)
1044 (setq file (car file-list) 1089 (setq file (car file-list)
1045 file-list (cdr file-list)) 1090 file-list (cdr file-list))
1046 (cond ((and file (or (not (stringp file)) (string= file ""))) 1091 (cond ((and file (or (not (stringp file)) (string= file "")))
1047 (error "(rolo-to): Invalid file: '%s'" file)) 1092 (error "(rolo-to): Invalid file: `%s'" file))
1048 ((and (file-exists-p file) (not (file-readable-p file))) 1093 ((and (file-exists-p file) (not (file-readable-p file)))
1049 (error "(rolo-to): File not readable: '%s'" file))) 1094 (error "(rolo-to): File not readable: `%s'" file)))
1050 (set-buffer (or (get-file-buffer file) (find-file-noselect file))) 1095 (set-buffer (or (get-file-buffer file) (find-file-noselect file)))
1051 (let ((case-fold-search t) (real-name name) (parent "") (level) end) 1096 (let ((case-fold-search t) (real-name name) (parent "") (level) end)
1052 (widen) (goto-char 1) 1097 (widen) (goto-char 1)
1053 (while (setq end (string-match "/" name)) 1098 (while (setq end (string-match "/" name))
1054 (setq level nil 1099 (setq level nil
1066 level)) 1111 level))
1067 ((equal name real-name));; Try next file. 1112 ((equal name real-name));; Try next file.
1068 (t;; Found parent but not child 1113 (t;; Found parent but not child
1069 (setq buffer-read-only nil) 1114 (setq buffer-read-only nil)
1070 (rolo-to-buffer (current-buffer)) 1115 (rolo-to-buffer (current-buffer))
1071 (error "(rolo-to): '%s' part of name not found in \"%s\"." 1116 (error "(rolo-to): `%s' part of name not found in \"%s\"."
1072 parent file))) 1117 parent file)))
1073 (if level 1118 (if level
1074 (narrow-to-region (point) 1119 (narrow-to-region (point)
1075 (save-excursion 1120 (save-excursion
1076 (rolo-to-entry-end t level) (point))))) 1121 (rolo-to-entry-end t level) (point)))))