diff options
| author | Karl Heuer | 1995-11-03 02:29:09 +0000 |
|---|---|---|
| committer | Karl Heuer | 1995-11-03 02:29:09 +0000 |
| commit | b3470e4c6b3b911f791446cf99170387c0900ad8 (patch) | |
| tree | 3004525a3e6cc7114a90d116774dd6919c8ad2b2 | |
| parent | 283b03f42d8edfaa78e859a8500e2c5f16af7179 (diff) | |
| download | emacs-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.el | 158 |
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, | |||
| 95 | with the default format file, to format messages when printing them. | 95 | with the default format file, to format messages when printing them. |
| 96 | The format used should specify a non-zero value for overflowoffset so | 96 | The format used should specify a non-zero value for overflowoffset so |
| 97 | the message continues to conform to RFC 822 and mh-e can parse the headers.") | 97 | the 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. |
| 442 | Optional non-nil second argument means return nil instead of | 464 | Optional non-nil second argument means return nil instead of |
| 443 | signaling an error if message does not exist. | 465 | signaling an error if message does not exist; in this case, |
| 466 | the cursor is positioned near where the message would have been. | ||
| 444 | Non-nil third argument means not to show the message." | 467 | Non-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 |