aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Heuer1995-11-03 02:29:09 +0000
committerKarl Heuer1995-11-03 02:29:09 +0000
commitb3470e4c6b3b911f791446cf99170387c0900ad8 (patch)
tree3004525a3e6cc7114a90d116774dd6919c8ad2b2
parent283b03f42d8edfaa78e859a8500e2c5f16af7179 (diff)
downloademacs-b3470e4c6b3b911f791446cf99170387c0900ad8.tar.gz
emacs-b3470e4c6b3b911f791446cf99170387c0900ad8.zip
(mh-goto-msg): binary search (much faster!).
(mh-prompt-for-folder): error if regular file.
-rw-r--r--lisp/mail/mh-utils.el158
1 files changed, 101 insertions, 57 deletions
diff --git a/lisp/mail/mh-utils.el b/lisp/mail/mh-utils.el
index cc06c774cd6..a77205a26d0 100644
--- a/lisp/mail/mh-utils.el
+++ b/lisp/mail/mh-utils.el
@@ -1,9 +1,9 @@
1;;; mh-utils.el --- mh-e code needed for both sending and reading 1;;; mh-utils.el --- mh-e code needed for both sending and reading
2;; Time-stamp: <95/02/10 14:20:14 gildea> 2;; Time-stamp: <95/10/22 17:58:16 gildea>
3 3
4;; Copyright (C) 1993, 1995 Free Software Foundation, Inc. 4;; Copyright (C) 1993, 1995 Free Software Foundation, Inc.
5 5
6;; This file is part of GNU Emacs. 6;; This file is part of mh-e, part of GNU Emacs.
7 7
8;; GNU Emacs is free software; you can redistribute it and/or modify 8;; GNU Emacs is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by 9;; it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
25 25
26;;; Change Log: 26;;; Change Log:
27 27
28;; $Id: mh-utils.el,v 1.4 1995/04/10 00:19:38 kwzh Exp kwzh $ 28;; $Id: mh-utils.el,v 1.5 1995/04/25 22:27:45 kwzh Exp kwzh $
29 29
30;;; Code: 30;;; Code:
31 31
@@ -95,6 +95,7 @@ Nil means don't use mhl to format messages when showing; mhl is still used,
95with the default format file, to format messages when printing them. 95with the default format file, to format messages when printing them.
96The format used should specify a non-zero value for overflowoffset so 96The format used should specify a non-zero value for overflowoffset so
97the message continues to conform to RFC 822 and mh-e can parse the headers.") 97the message continues to conform to RFC 822 and mh-e can parse the headers.")
98(put 'mhl-formfile 'info-file "mh-e")
98 99
99(defvar mh-default-folder-for-message-function nil 100(defvar mh-default-folder-for-message-function nil
100 "Function to select a default folder for refiling or Fcc. 101 "Function to select a default folder for refiling or Fcc.
@@ -158,6 +159,8 @@ First argument is folder name. Second is message number.")
158(defvar mh-show-buffer nil) ;Buffer that displays message for this folder. 159(defvar mh-show-buffer nil) ;Buffer that displays message for this folder.
159 160
160(defvar mh-folder-filename nil) ;Full path of directory for this folder. 161(defvar mh-folder-filename nil) ;Full path of directory for this folder.
162
163(defvar mh-msg-count nil) ;Number of msgs in buffer.
161 164
162(defvar mh-showing nil) ;If non-nil, show the message in a separate window. 165(defvar mh-showing nil) ;If non-nil, show the message in a separate window.
163 166
@@ -421,7 +424,7 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
421 424
422(defun mh-delete-line (lines) 425(defun mh-delete-line (lines)
423 ;; Delete version of kill-line. 426 ;; Delete version of kill-line.
424 (delete-region (point) (save-excursion (forward-line lines) (point)))) 427 (delete-region (point) (progn (forward-line lines) (point))))
425 428
426 429
427(defun mh-notate (msg notation offset) 430(defun mh-notate (msg notation offset)
@@ -437,34 +440,59 @@ Type \"\\[mh-header-display]\" to see the message with all its headers."
437 (insert notation))))) 440 (insert notation)))))
438 441
439 442
443(defun mh-find-msg-get-num (step)
444 ;; Return the message number of the message on the current scan line
445 ;; or one nearby. Jumps over non-message lines, such as inc errors.
446 ;; STEP tells whether to search forward or backward if we have to search.
447 (or (mh-get-msg-num nil)
448 (let ((msg-num nil)
449 (nreverses 0))
450 (while (and (not msg-num)
451 (< nreverses 2))
452 (cond ((eobp)
453 (setq step -1)
454 (setq nreverses (1+ nreverses)))
455 ((bobp)
456 (setq step 1)
457 (setq nreverses (1+ nreverses))))
458 (forward-line step)
459 (setq msg-num (mh-get-msg-num nil)))
460 msg-num)))
461
440(defun mh-goto-msg (number &optional no-error-if-no-message dont-show) 462(defun mh-goto-msg (number &optional no-error-if-no-message dont-show)
441 "Position the cursor at message NUMBER. 463 "Position the cursor at message NUMBER.
442Optional non-nil second argument means return nil instead of 464Optional non-nil second argument means return nil instead of
443signaling an error if message does not exist. 465signaling an error if message does not exist; in this case,
466the cursor is positioned near where the message would have been.
444Non-nil third argument means not to show the message." 467Non-nil third argument means not to show the message."
445 (interactive "NGo to message: ") 468 (interactive "NGo to message: ")
446 (setq number (prefix-numeric-value number)) ;Emacs 19 469 (setq number (prefix-numeric-value number)) ;Emacs 19
447 (let ((cur-msg (mh-get-msg-num nil)) 470 ;; This basic routine tries to be as fast as possible,
448 (starting-place (point)) 471 ;; using a binary search and minimal regexps.
449 (msg-pattern (mh-msg-search-pat number))) 472 (let ((cur-msg (mh-find-msg-get-num -1))
450 (cond ((cond ((and cur-msg (= cur-msg number)) t) 473 (jump-size mh-msg-count))
451 ((and cur-msg 474 (while (and (> jump-size 1)
452 (< cur-msg number) 475 cur-msg
453 (re-search-forward msg-pattern nil t)) t) 476 (not (eq cur-msg number)))
454 ((and cur-msg 477 (cond ((< cur-msg number)
455 (> cur-msg number) 478 (setq jump-size (min (- number cur-msg)
456 (re-search-backward msg-pattern nil t)) t) 479 (ash (1+ jump-size) -1)))
457 (t ; Do thorough search of buffer 480 (forward-line jump-size)
458 (goto-char (point-max)) 481 (setq cur-msg (mh-find-msg-get-num 1)))
459 (re-search-backward msg-pattern nil t))) 482 (t
460 (beginning-of-line) 483 (setq jump-size (min (- cur-msg number)
461 (if (not dont-show) (mh-maybe-show number)) 484 (ash (1+ jump-size) -1)))
462 t) 485 (forward-line (- jump-size))
463 (t 486 (setq cur-msg (mh-find-msg-get-num -1)))))
464 (goto-char starting-place) 487 (if (eq cur-msg number)
465 (if (not no-error-if-no-message) 488 (progn
466 (error "No message %d" number)) 489 (beginning-of-line)
467 nil)))) 490 (or dont-show
491 (mh-maybe-show number)
492 t))
493 (if (not no-error-if-no-message)
494 (error "No message %d" number)))))
495
468 496
469(defun mh-msg-search-pat (n) 497(defun mh-msg-search-pat (n)
470 ;; Return a search pattern for message N in the scan listing. 498 ;; Return a search pattern for message N in the scan listing.
@@ -484,6 +512,7 @@ Non-nil third argument means not to show the message."
484 (end-of-line) 512 (end-of-line)
485 (buffer-substring start (point))))))) 513 (buffer-substring start (point)))))))
486 514
515(defvar mua-paradigm "MH-E") ;from mua.el
487 516
488(defun mh-find-path () 517(defun mh-find-path ()
489 ;; Set mh-progs and mh-lib. 518 ;; Set mh-progs and mh-lib.
@@ -527,6 +556,7 @@ Non-nil third argument means not to show the message."
527 (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:")) 556 (setq mh-previous-seq (mh-get-profile-field "Previous-Sequence:"))
528 (if mh-previous-seq 557 (if mh-previous-seq
529 (setq mh-previous-seq (intern mh-previous-seq))) 558 (setq mh-previous-seq (intern mh-previous-seq)))
559 (setq mua-paradigm "MH-E")
530 (run-hooks 'mh-find-path-hook)))) 560 (run-hooks 'mh-find-path-hook))))
531 561
532(defun mh-find-progs () 562(defun mh-find-progs ()
@@ -565,13 +595,17 @@ Non-nil third argument means not to show the message."
565 (setq path (cdr path))) 595 (setq path (cdr path)))
566 (car path)) 596 (car path))
567 597
598(defvar mh-no-install nil) ;do not run install-mh
599
568(defun mh-install (profile error-val) 600(defun mh-install (profile error-val)
569 ;; Called to do error recovery if we fail to read the profile file. 601 ;; Called to do error recovery if we fail to read the profile file.
570 ;; If possible, initialize the MH environment. 602 ;; If possible, initialize the MH environment.
571 (if (or (getenv "MH") 603 (if (or (getenv "MH")
572 (file-exists-p profile)) 604 (file-exists-p profile)
573 (error "Cannot read MH profile \"%s\": %s" 605 mh-no-install)
574 profile (car (cdr (cdr error-val))))) 606 (signal (car error-val)
607 (list (format "Cannot read MH profile \"%s\"" profile)
608 (car (cdr (cdr error-val))))))
575 ;; The "install-mh" command will output a short note which 609 ;; The "install-mh" command will output a short note which
576 ;; mh-exec-cmd will display to the user. 610 ;; mh-exec-cmd will display to the user.
577 ;; The MH 5 version of install-mh might try prompt the user 611 ;; The MH 5 version of install-mh might try prompt the user
@@ -582,8 +616,9 @@ Non-nil third argument means not to show the message."
582 (condition-case err 616 (condition-case err
583 (insert-file-contents profile) 617 (insert-file-contents profile)
584 (file-error 618 (file-error
585 (error "Cannot read MH profile \"%s\": %s" 619 (signal (car err) ;re-signal with more specific msg
586 profile (car (cdr (cdr err))))))) 620 (list (format "Cannot read MH profile \"%s\"" profile)
621 (car (cdr (cdr err))))))))
587 622
588 623
589(defun mh-set-folder-modified-p (flag) 624(defun mh-set-folder-modified-p (flag)
@@ -658,6 +693,9 @@ Non-nil third argument means not to show the message."
658 (run-hooks 'mh-folder-list-change-hook)) 693 (run-hooks 'mh-folder-list-change-hook))
659 (new-file-p 694 (new-file-p
660 (error "Folder %s is not created" folder-name)) 695 (error "Folder %s is not created" folder-name))
696 ((not (file-directory-p (mh-expand-file-name folder-name)))
697 (error "\"%s\" is not a directory"
698 (mh-expand-file-name folder-name)))
661 ((and (null (assoc read-name mh-folder-list)) 699 ((and (null (assoc read-name mh-folder-list))
662 (null (assoc (concat read-name "/") mh-folder-list))) 700 (null (assoc (concat read-name "/") mh-folder-list)))
663 (setq mh-folder-list (cons (list read-name) mh-folder-list)) 701 (setq mh-folder-list (cons (list read-name) mh-folder-list))
@@ -692,7 +730,7 @@ Non-nil third argument means not to show the message."
692 ;; Call mh-set-folder-list to wait for the result. 730 ;; Call mh-set-folder-list to wait for the result.
693 (cond 731 (cond
694 ((not mh-make-folder-list-process) 732 ((not mh-make-folder-list-process)
695 (mh-find-progs) 733 (mh-find-path)
696 (let ((process-connection-type nil)) 734 (let ((process-connection-type nil))
697 (setq mh-make-folder-list-process 735 (setq mh-make-folder-list-process
698 (start-process "folders" nil (expand-file-name "folders" mh-progs) 736 (start-process "folders" nil (expand-file-name "folders" mh-progs)
@@ -707,32 +745,35 @@ Non-nil third argument means not to show the message."
707(defun mh-make-folder-list-filter (process output) 745(defun mh-make-folder-list-filter (process output)
708 ;; parse output from "folders -fast" 746 ;; parse output from "folders -fast"
709 (let ((position 0) 747 (let ((position 0)
710 (line-end t) 748 line-end
711 new-folder) 749 new-folder
712 (while line-end 750 (prevailing-match-data (match-data)))
713 (setq line-end (string-match "\n" output position)) 751 (unwind-protect
714 (cond 752 ;; make sure got complete line
715 (line-end ;make sure got complete line 753 (while (setq line-end (string-match "\n" output position))
716 (setq new-folder (format "+%s%s" 754 (setq new-folder (format "+%s%s"
717 mh-folder-list-partial-line 755 mh-folder-list-partial-line
718 (substring output position line-end))) 756 (substring output position line-end)))
719 (setq mh-folder-list-partial-line "") 757 (setq mh-folder-list-partial-line "")
720 ;; is new folder a subfolder of previous? 758 ;; is new folder a subfolder of previous?
721 (if (and mh-folder-list-temp 759 (if (and mh-folder-list-temp
722 (string-match (regexp-quote 760 (string-match
723 (concat (car (car mh-folder-list-temp)) "/")) 761 (regexp-quote
724 new-folder)) 762 (concat (car (car mh-folder-list-temp)) "/"))
725 ;; append slash to parent folder for better completion 763 new-folder))
726 ;; (undone by mh-prompt-for-folder) 764 ;; append slash to parent folder for better completion
765 ;; (undone by mh-prompt-for-folder)
766 (setq mh-folder-list-temp
767 (cons
768 (list new-folder)
769 (cons
770 (list (concat (car (car mh-folder-list-temp)) "/"))
771 (cdr mh-folder-list-temp))))
727 (setq mh-folder-list-temp 772 (setq mh-folder-list-temp
728 (cons (list new-folder) 773 (cons (list new-folder)
729 (cons 774 mh-folder-list-temp)))
730 (list (concat (car (car mh-folder-list-temp)) "/")) 775 (setq position (1+ line-end)))
731 (cdr mh-folder-list-temp)))) 776 (store-match-data prevailing-match-data))
732 (setq mh-folder-list-temp
733 (cons (list new-folder)
734 mh-folder-list-temp)))
735 (setq position (1+ line-end)))))
736 (setq mh-folder-list-partial-line (substring output position)))) 777 (setq mh-folder-list-partial-line (substring output position))))
737 778
738 779
@@ -903,6 +944,9 @@ Non-nil third argument means not to show the message."
903 944
904(and (not noninteractive) 945(and (not noninteractive)
905 mh-auto-folder-collect 946 mh-auto-folder-collect
906 (mh-make-folder-list-background)) 947 (let ((mh-no-install t)) ;only get folders if MH installed
948 (condition-case err
949 (mh-make-folder-list-background)
950 (file-error)))) ;so don't complain if not installed
907 951
908;;; mh-utils.el ends here 952;;; mh-utils.el ends here