comparison lisp/mh-e/mh-seq.el @ 56673:e9a6cbc8ca5e

Upgraded to MH-E version 7.4.80. See etc/MH-E-NEWS and lisp/mh-e/ChangeLog for details.
author Bill Wohler <wohler@newt.com>
date Sun, 15 Aug 2004 22:00:06 +0000
parents d36b00b98db0
children 4f4f410e6fe8 d8411455de48
comparison
equal deleted inserted replaced
56672:83ab2b01744a 56673:e9a6cbc8ca5e
68 68
69 ;;; Change Log: 69 ;;; Change Log:
70 70
71 ;;; Code: 71 ;;; Code:
72 72
73 (require 'mh-utils) 73 (eval-when-compile (require 'mh-acros))
74 (mh-require-cl) 74 (mh-require-cl)
75 (require 'mh-e) 75 (require 'mh-e)
76 76
77 ;; Shush the byte-compiler 77 ;; Shush the byte-compiler
78 (defvar tool-bar-mode) 78 (defvar tool-bar-mode)
79 79
80 ;;; Data structures (used in message threading)... 80 ;;; Data structures (used in message threading)...
81 (defstruct (mh-thread-message (:conc-name mh-message-) 81 (mh-defstruct (mh-thread-message (:conc-name mh-message-)
82 (:constructor mh-thread-make-message)) 82 (:constructor mh-thread-make-message))
83 (id nil) 83 (id nil)
84 (references ()) 84 (references ())
85 (subject "") 85 (subject "")
86 (subject-re-p nil)) 86 (subject-re-p nil))
87 87
88 (defstruct (mh-thread-container (:conc-name mh-container-) 88 (mh-defstruct (mh-thread-container (:conc-name mh-container-)
89 (:constructor mh-thread-make-container)) 89 (:constructor mh-thread-make-container))
90 message parent children 90 message parent children
91 (real-child-p t)) 91 (real-child-p t))
92 92
93 93
94 ;;; Internal variables: 94 ;;; Internal variables:
199 (setq view-exit-action 'kill-buffer) 199 (setq view-exit-action 'kill-buffer)
200 (message "Listing sequences...done"))))) 200 (message "Listing sequences...done")))))
201 201
202 ;;;###mh-autoload 202 ;;;###mh-autoload
203 (defun mh-msg-is-in-seq (message) 203 (defun mh-msg-is-in-seq (message)
204 "Display the sequences that contain MESSAGE. 204 "Display the sequences in which the current message appears.
205 Default is the displayed message." 205 Use a prefix argument to display the sequences in which another MESSAGE
206 (interactive (list (mh-get-msg-num t))) 206 appears."
207 (interactive "P")
208 (if (not message)
209 (setq message (mh-get-msg-num t)))
207 (let* ((dest-folder (loop for seq in mh-refile-list 210 (let* ((dest-folder (loop for seq in mh-refile-list
208 until (member message (cdr seq)) 211 when (member message (cdr seq)) return (car seq)
209 finally return (car seq))) 212 finally return nil))
210 (deleted-flag (unless dest-folder (member message mh-delete-list)))) 213 (deleted-flag (unless dest-folder (member message mh-delete-list))))
211 (message "Message %d%s is in sequences: %s" 214 (message "Message %d%s is in sequences: %s"
212 message 215 message
213 (cond (dest-folder (format " (to be refiled to %s)" dest-folder)) 216 (cond (dest-folder (format " (to be refiled to %s)" dest-folder))
214 (deleted-flag (format " (to be deleted)")) 217 (deleted-flag (format " (to be deleted)"))
267 (unless (mh-valid-seq-p sequence) 270 (unless (mh-valid-seq-p sequence)
268 (error "Can't put message in invalid sequence `%s'" sequence)) 271 (error "Can't put message in invalid sequence `%s'" sequence))
269 (let* ((internal-seq-flag (mh-internal-seq sequence)) 272 (let* ((internal-seq-flag (mh-internal-seq sequence))
270 (original-msgs (mh-seq-msgs (mh-find-seq sequence))) 273 (original-msgs (mh-seq-msgs (mh-find-seq sequence)))
271 (folders (list mh-current-folder)) 274 (folders (list mh-current-folder))
272 (msg-list ())) 275 (msg-list (mh-range-to-msg-list range)))
276 (mh-add-msgs-to-seq msg-list sequence nil t)
273 (mh-iterate-on-range m range 277 (mh-iterate-on-range m range
274 (push m msg-list)
275 (unless (memq m original-msgs) 278 (unless (memq m original-msgs)
276 (mh-add-sequence-notation m internal-seq-flag))) 279 (mh-add-sequence-notation m internal-seq-flag)))
277 (mh-add-msgs-to-seq msg-list sequence nil t)
278 (if (not internal-seq-flag) 280 (if (not internal-seq-flag)
279 (setq mh-last-seq-used sequence)) 281 (setq mh-last-seq-used sequence))
280 (when mh-index-data 282 (when mh-index-data
281 (setq folders 283 (setq folders
282 (append folders (mh-index-add-to-sequence sequence msg-list)))) 284 (append folders (mh-index-add-to-sequence sequence msg-list))))
290 (pop mh-view-ops)) 292 (pop mh-view-ops))
291 (t nil))) 293 (t nil)))
292 294
293 ;;;###mh-autoload 295 ;;;###mh-autoload
294 (defun mh-widen (&optional all-flag) 296 (defun mh-widen (&optional all-flag)
295 "Remove last restriction from current folder. 297 "Restore the previous limit.
296 If optional prefix argument ALL-FLAG is non-nil, then unwind to the beginning 298 If optional prefix argument ALL-FLAG is non-nil, remove all limits."
297 of the view stack thereby showing all messages that the buffer originally
298 contained."
299 (interactive "P") 299 (interactive "P")
300 (let ((msg (mh-get-msg-num nil))) 300 (let ((msg (mh-get-msg-num nil)))
301 (when mh-folder-view-stack 301 (when mh-folder-view-stack
302 (cond (all-flag 302 (cond (all-flag
303 (while (cdr mh-view-ops) 303 (while (cdr mh-view-ops)
531 (mh-define-sequence new-name (mh-seq-msgs old-seq)) 531 (mh-define-sequence new-name (mh-seq-msgs old-seq))
532 (mh-undefine-sequence sequence (mh-seq-msgs old-seq)) 532 (mh-undefine-sequence sequence (mh-seq-msgs old-seq))
533 (rplaca old-seq new-name))) 533 (rplaca old-seq new-name)))
534 534
535 ;;;###mh-autoload 535 ;;;###mh-autoload
536 (defun mh-map-to-seq-msgs (func seq &rest args)
537 "Invoke the FUNC at each message in the SEQ.
538 SEQ can either be a list of messages or a MH sequence. The remaining ARGS are
539 passed as arguments to FUNC."
540 (save-excursion
541 (let ((msgs (if (listp seq) seq (mh-seq-to-msgs seq))))
542 (while msgs
543 (if (mh-goto-msg (car msgs) t t)
544 (apply func (car msgs) args))
545 (setq msgs (cdr msgs))))))
546
547 ;;;###mh-autoload
548 (defun mh-notate-seq (seq notation offset)
549 "Mark the scan listing.
550 All messages in SEQ are marked with NOTATION at OFFSET from the beginning of
551 the line."
552 (let ((msg-list (mh-seq-to-msgs seq)))
553 (mh-iterate-on-messages-in-region msg (point-min) (point-max)
554 (when (member msg msg-list)
555 (mh-notate nil notation offset)))))
556
557 ;;;###mh-autoload
558 (defun mh-notate-cur () 536 (defun mh-notate-cur ()
559 "Mark the MH sequence cur. 537 "Mark the MH sequence cur.
560 In addition to notating the current message with `mh-note-cur' the function 538 In addition to notating the current message with `mh-note-cur' the function
561 uses `overlay-arrow-position' to put a marker in the fringe." 539 uses `overlay-arrow-position' to put a marker in the fringe."
562 (let ((cur (car (mh-seq-to-msgs 'cur)))) 540 (let ((cur (car (mh-seq-to-msgs 'cur))))
574 (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq))) 552 (if (and (mh-valid-seq-p seq) (not (mh-folder-name-p seq)))
575 (if msgs 553 (if msgs
576 (apply 'mh-exec-cmd "mark" mh-current-folder "-add" 554 (apply 'mh-exec-cmd "mark" mh-current-folder "-add"
577 "-sequence" (symbol-name seq) 555 "-sequence" (symbol-name seq)
578 (mh-coalesce-msg-list msgs))))) 556 (mh-coalesce-msg-list msgs)))))
579
580 ;; This has a tricky bug. mh-map-to-seq-msgs uses mh-goto-msg, which assumes
581 ;; that the folder buffer is sorted. However in this case that assumption
582 ;; doesn't hold. So we will do this the dumb way.
583 ;(defun mh-copy-seq-to-point (seq location)
584 ; ;; Copy the scan listing of the messages in SEQUENCE to after the point
585 ; ;; LOCATION in the current buffer.
586 ; (mh-map-to-seq-msgs 'mh-copy-line-to-point seq location))
587 557
588 (defvar mh-thread-last-ancestor) 558 (defvar mh-thread-last-ancestor)
589 559
590 (defun mh-copy-seq-to-eob (seq) 560 (defun mh-copy-seq-to-eob (seq)
591 "Copy SEQ to the end of the buffer." 561 "Copy SEQ to the end of the buffer."
611 (mh-thread-print-scan-lines 581 (mh-thread-print-scan-lines
612 (mh-thread-generate mh-current-folder ())) 582 (mh-thread-generate mh-current-folder ()))
613 (mh-notate-user-sequences)) 583 (mh-notate-user-sequences))
614 (mh-index-data 584 (mh-index-data
615 (mh-index-insert-folder-headers))))))) 585 (mh-index-insert-folder-headers)))))))
616
617 (defun mh-copy-line-to-point (msg location)
618 "Copy current message line to a specific location.
619 The argument MSG is not used. The message in the current line is copied to
620 LOCATION."
621 ;; msg is not used?
622 ;; Copy the current line to the LOCATION in the current buffer.
623 (beginning-of-line)
624 (save-excursion
625 (let ((beginning-of-line (point))
626 end)
627 (forward-line 1)
628 (setq end (point))
629 (goto-char location)
630 (insert-buffer-substring (current-buffer) beginning-of-line end))))
631 586
632 ;;;###mh-autoload 587 ;;;###mh-autoload
633 (defmacro mh-iterate-on-messages-in-region (var begin end &rest body) 588 (defmacro mh-iterate-on-messages-in-region (var begin end &rest body)
634 "Iterate over region. 589 "Iterate over region.
635 VAR is bound to the message on the current line as we loop starting from BEGIN 590 VAR is bound to the message on the current line as we loop starting from BEGIN
700 (mh-iterate-on-range msg range 655 (mh-iterate-on-range msg range
701 (push msg msg-list)) 656 (push msg msg-list))
702 (nreverse msg-list))) 657 (nreverse msg-list)))
703 658
704 ;;;###mh-autoload 659 ;;;###mh-autoload
705 (defun mh-interactive-range (range-prompt) 660 (defun mh-interactive-range (range-prompt &optional default)
706 "Return interactive specification for message, sequence, range or region. 661 "Return interactive specification for message, sequence, range or region.
707 By convention, the name of this argument is RANGE. 662 By convention, the name of this argument is RANGE.
708 663
709 If variable `transient-mark-mode' is non-nil and the mark is active, then this 664 If variable `transient-mark-mode' is non-nil and the mark is active, then this
710 function returns a cons-cell of the region. 665 function returns a cons-cell of the region.
712 If optional prefix argument is provided, then prompt for message range with 667 If optional prefix argument is provided, then prompt for message range with
713 RANGE-PROMPT. A list of messages in that range is returned. 668 RANGE-PROMPT. A list of messages in that range is returned.
714 669
715 If a MH range is given, say something like last:20, then a list containing 670 If a MH range is given, say something like last:20, then a list containing
716 the messages in that range is returned. 671 the messages in that range is returned.
672
673 If DEFAULT non-nil then it is returned.
717 674
718 Otherwise, the message number at point is returned. 675 Otherwise, the message number at point is returned.
719 676
720 This function is usually used with `mh-iterate-on-range' in order to provide 677 This function is usually used with `mh-iterate-on-range' in order to provide
721 a uniform interface to MH-E functions." 678 a uniform interface to MH-E functions."
722 (cond ((mh-mark-active-p t) (cons (region-beginning) (region-end))) 679 (cond ((mh-mark-active-p t) (cons (region-beginning) (region-end)))
723 (current-prefix-arg (mh-read-range range-prompt nil nil t t)) 680 (current-prefix-arg (mh-read-range range-prompt nil nil t t))
681 (default default)
724 (t (mh-get-msg-num t)))) 682 (t (mh-get-msg-num t))))
725
726 ;;;###mh-autoload
727 (defun mh-region-to-msg-list (begin end)
728 "Return a list of messages within the region between BEGIN and END."
729 ;; If end is end of buffer back up one position
730 (setq end (if (equal end (point-max)) (1- end) end))
731 (let ((result))
732 (mh-iterate-on-messages-in-region index begin end
733 (when (numberp index) (push index result)))
734 result))
735 683
736 684
737 685
738 ;;; Commands to handle new 'subject sequence. 686 ;;; Commands to handle new 'subject sequence.
739 ;;; Or "Poor man's threading" by psg. 687 ;;; Or "Poor man's threading" by psg.
770 (save-excursion 718 (save-excursion
771 (beginning-of-line) 719 (beginning-of-line)
772 (if (or (not (looking-at mh-scan-subject-regexp)) 720 (if (or (not (looking-at mh-scan-subject-regexp))
773 (not (match-string 3)) 721 (not (match-string 3))
774 (string-equal "" (match-string 3))) 722 (string-equal "" (match-string 3)))
775 (progn (message "No subject line.") 723 (progn (message "No subject line")
776 nil) 724 nil)
777 (let ((subject (match-string-no-properties 3)) 725 (let ((subject (match-string-no-properties 3))
778 (list)) 726 (list))
779 (if (> (length subject) 41) 727 (if (> (length subject) 41)
780 (setq subject (substring subject 0 41))) 728 (setq subject (substring subject 0 41)))
833 (ignore-errors 781 (ignore-errors
834 (mh-message-subject 782 (mh-message-subject
835 (mh-container-message (gethash (gethash msg mh-thread-index-id-map) 783 (mh-container-message (gethash (gethash msg mh-thread-index-id-map)
836 mh-thread-id-table))))) 784 mh-thread-id-table)))))
837 785
838 ;;;###mh-autoload 786 (defun mh-edit-pick-expr (default)
839 (defun mh-narrow-to-subject () 787 "With prefix arg edit a pick expression.
840 "Narrow to a sequence containing all following messages with same subject."
841 (interactive)
842 (let ((num (mh-get-msg-num nil))
843 (count (mh-subject-to-sequence t)))
844 (cond
845 ((not count) ; No subject line, delete msg anyway
846 nil)
847 ((= 0 count) ; No other msgs, delete msg anyway.
848 (message "No other messages with same Subject following this one.")
849 nil)
850 (t ; We have a subject sequence.
851 (message "Found %d messages for subject sequence." count)
852 (mh-narrow-to-seq 'subject)
853 (if (numberp num)
854 (mh-goto-msg num t t))))))
855
856 (defun mh-read-pick-regexp (default)
857 "With prefix arg read a pick regexp.
858 If no prefix arg is given, then return DEFAULT." 788 If no prefix arg is given, then return DEFAULT."
859 (let ((default-string (loop for x in default concat (format " %s" x)))) 789 (let ((default-string (loop for x in default concat (format " %s" x))))
860 (if (or current-prefix-arg (equal default-string "")) 790 (if (or current-prefix-arg (equal default-string ""))
861 (delete "" (split-string (read-string "Pick regexp: " default-string))) 791 (delete "" (split-string (read-string "Pick expression: "
792 default-string)))
862 default))) 793 default)))
863 794
864 ;;;###mh-autoload 795 ;;;###mh-autoload
865 (defun mh-narrow-to-from (&optional regexp) 796 (defun mh-narrow-to-subject (&optional pick-expr)
866 "Limit to messages with the same From header field as the message at point. 797 "Limit to messages with same subject.
867 With a prefix argument, prompt for the regular expression, REGEXP given to 798 With a prefix argument, edit PICK-EXPR.
868 pick." 799
800 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
869 (interactive 801 (interactive
870 (list (mh-read-pick-regexp (mh-current-message-header-field 'from)))) 802 (list (mh-edit-pick-expr (mh-current-message-header-field 'subject))))
871 (mh-narrow-to-header-field 'from regexp)) 803 (mh-narrow-to-header-field 'subject pick-expr))
872 804
873 ;;;###mh-autoload 805 ;;;###mh-autoload
874 (defun mh-narrow-to-cc (&optional regexp) 806 (defun mh-narrow-to-from (&optional pick-expr)
875 "Limit to messages with the same Cc header field as the message at point. 807 "Limit to messages with the same `From:' field.
876 With a prefix argument, prompt for the regular expression, REGEXP given to 808 With a prefix argument, edit PICK-EXPR.
877 pick." 809
810 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
878 (interactive 811 (interactive
879 (list (mh-read-pick-regexp (mh-current-message-header-field 'cc)))) 812 (list (mh-edit-pick-expr (mh-current-message-header-field 'from))))
880 (mh-narrow-to-header-field 'cc regexp)) 813 (mh-narrow-to-header-field 'from pick-expr))
881 814
882 ;;;###mh-autoload 815 ;;;###mh-autoload
883 (defun mh-narrow-to-to (&optional regexp) 816 (defun mh-narrow-to-cc (&optional pick-expr)
884 "Limit to messages with the same To header field as the message at point. 817 "Limit to messages with the same `Cc:' field.
885 With a prefix argument, prompt for the regular expression, REGEXP given to 818 With a prefix argument, edit PICK-EXPR.
886 pick." 819
820 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
887 (interactive 821 (interactive
888 (list (mh-read-pick-regexp (mh-current-message-header-field 'to)))) 822 (list (mh-edit-pick-expr (mh-current-message-header-field 'cc))))
889 (mh-narrow-to-header-field 'to regexp)) 823 (mh-narrow-to-header-field 'cc pick-expr))
890 824
891 (defun mh-narrow-to-header-field (header-field regexp) 825 ;;;###mh-autoload
892 "Limit to messages whose HEADER-FIELD match REGEXP. 826 (defun mh-narrow-to-to (&optional pick-expr)
827 "Limit to messages with the same `To:' field.
828 With a prefix argument, edit PICK-EXPR.
829
830 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
831 (interactive
832 (list (mh-edit-pick-expr (mh-current-message-header-field 'to))))
833 (mh-narrow-to-header-field 'to pick-expr))
834
835 (defun mh-narrow-to-header-field (header-field pick-expr)
836 "Limit to messages whose HEADER-FIELD match PICK-EXPR.
893 The MH command pick is used to do the match." 837 The MH command pick is used to do the match."
894 (let ((folder mh-current-folder) 838 (let ((folder mh-current-folder)
895 (original (mh-coalesce-msg-list 839 (original (mh-coalesce-msg-list
896 (mh-range-to-msg-list (cons (point-min) (point-max))))) 840 (mh-range-to-msg-list (cons (point-min) (point-max)))))
897 (msg-list ())) 841 (msg-list ()))
898 (with-temp-buffer 842 (with-temp-buffer
899 (apply #'mh-exec-cmd-output "pick" nil folder 843 (apply #'mh-exec-cmd-output "pick" nil folder
900 (append original (list "-list") regexp)) 844 (append original (list "-list") pick-expr))
901 (goto-char (point-min)) 845 (goto-char (point-min))
902 (while (not (eobp)) 846 (while (not (eobp))
903 (let ((num (read-from-string 847 (let ((num (read-from-string
904 (buffer-substring (point) (line-end-position))))) 848 (buffer-substring (point) (line-end-position)))))
905 (when (numberp (car num)) (push (car num) msg-list)) 849 (when (numberp (car num)) (push (car num) msg-list))
937 ;;;###mh-autoload 881 ;;;###mh-autoload
938 (defun mh-narrow-to-range (range) 882 (defun mh-narrow-to-range (range)
939 "Limit to messages in RANGE. 883 "Limit to messages in RANGE.
940 884
941 Check the documentation of `mh-interactive-range' to see how RANGE is read in 885 Check the documentation of `mh-interactive-range' to see how RANGE is read in
942 interactive use." 886 interactive use.
887
888 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
943 (interactive (list (mh-interactive-range "Narrow to"))) 889 (interactive (list (mh-interactive-range "Narrow to")))
944 (when (assoc 'range mh-seq-list) (mh-delete-seq 'range)) 890 (when (assoc 'range mh-seq-list) (mh-delete-seq 'range))
945 (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range) 891 (mh-add-msgs-to-seq (mh-range-to-msg-list range) 'range)
946 (mh-narrow-to-seq 'range)) 892 (mh-narrow-to-seq 'range))
947 893
956 (let ((count (mh-subject-to-sequence nil))) 902 (let ((count (mh-subject-to-sequence nil)))
957 (cond 903 (cond
958 ((not count) ; No subject line, delete msg anyway 904 ((not count) ; No subject line, delete msg anyway
959 (mh-delete-msg (mh-get-msg-num t))) 905 (mh-delete-msg (mh-get-msg-num t)))
960 ((= 0 count) ; No other msgs, delete msg anyway. 906 ((= 0 count) ; No other msgs, delete msg anyway.
961 (message "No other messages with same Subject following this one.") 907 (message "No other messages with same Subject following this one")
962 (mh-delete-msg (mh-get-msg-num t))) 908 (mh-delete-msg (mh-get-msg-num t)))
963 (t ; We have a subject sequence. 909 (t ; We have a subject sequence.
964 (message "Marked %d messages for deletion" count) 910 (message "Marked %d messages for deletion" count)
965 (mh-delete-msg 'subject))))) 911 (mh-delete-msg 'subject)))))
966 912
1076 (setf (mh-message-id message) id) 1022 (setf (mh-message-id message) id)
1077 (setf (mh-message-references message) refs) 1023 (setf (mh-message-references message) refs)
1078 message) 1024 message)
1079 (container 1025 (container
1080 (setf (mh-container-message container) 1026 (setf (mh-container-message container)
1081 (mh-thread-make-message :subject subject 1027 (mh-thread-make-message :id id :references refs
1082 :subject-re-p subject-re-p 1028 :subject subject
1083 :id id :references refs))) 1029 :subject-re-p subject-re-p)))
1084 (t (let ((message (mh-thread-make-message 1030 (t (let ((message (mh-thread-make-message :id id :references refs
1085 :subject subject 1031 :subject-re-p subject-re-p
1086 :subject-re-p subject-re-p 1032 :subject subject)))
1087 :id id :references refs)))
1088 (prog1 message 1033 (prog1 message
1089 (mh-thread-get-message-container message))))))) 1034 (mh-thread-get-message-container message)))))))
1090 1035
1091 (defsubst mh-thread-canonicalize-id (id) 1036 (defsubst mh-thread-canonicalize-id (id)
1092 "Produce canonical string representation for ID. 1037 "Produce canonical string representation for ID.
1448 MSG is the message being notated with NOTATION at OFFSET." 1393 MSG is the message being notated with NOTATION at OFFSET."
1449 (let* ((msg (or msg (mh-get-msg-num nil))) 1394 (let* ((msg (or msg (mh-get-msg-num nil)))
1450 (cur-scan-line (and mh-thread-scan-line-map 1395 (cur-scan-line (and mh-thread-scan-line-map
1451 (gethash msg mh-thread-scan-line-map))) 1396 (gethash msg mh-thread-scan-line-map)))
1452 (old-scan-lines (loop for map in mh-thread-scan-line-map-stack 1397 (old-scan-lines (loop for map in mh-thread-scan-line-map-stack
1453 collect (and map (gethash msg map)))) 1398 collect (and map (gethash msg map)))))
1454 (notation (if (stringp notation) (aref notation 0) notation)))
1455 (when cur-scan-line 1399 (when cur-scan-line
1456 (setf (aref (car cur-scan-line) offset) notation)) 1400 (setf (aref (car cur-scan-line) offset) notation))
1457 (dolist (line old-scan-lines) 1401 (dolist (line old-scan-lines)
1458 (when line (setf (aref (car line) offset) notation))))) 1402 (when line (setf (aref (car line) offset) notation)))))
1459 1403
1484 do (let ((v (gethash msg old-map))) 1428 do (let ((v (gethash msg old-map)))
1485 (when v 1429 (when v
1486 (setf (gethash msg mh-thread-scan-line-map) v)))) 1430 (setf (gethash msg mh-thread-scan-line-map) v))))
1487 (when (> (hash-table-count mh-thread-scan-line-map) 0) 1431 (when (> (hash-table-count mh-thread-scan-line-map) 0)
1488 (insert (if (bobp) "" "\n") (car x) "\n") 1432 (insert (if (bobp) "" "\n") (car x) "\n")
1489 (mh-thread-generate-scan-lines thread-tree -2))))))) 1433 (mh-thread-generate-scan-lines thread-tree -2))))
1434 (mh-index-create-imenu-index))))
1490 1435
1491 (defun mh-thread-folder () 1436 (defun mh-thread-folder ()
1492 "Generate thread view of folder." 1437 "Generate thread view of folder."
1493 (message "Threading %s..." (buffer-name)) 1438 (message "Threading %s..." (buffer-name))
1494 (mh-thread-initialize) 1439 (mh-thread-initialize)
1709 (mh-iterate-on-range msg range 1654 (mh-iterate-on-range msg range
1710 (cond ((member msg tick-seq-msgs) 1655 (cond ((member msg tick-seq-msgs)
1711 (push msg unticked) 1656 (push msg unticked)
1712 (setcdr tick-seq (delq msg (cdr tick-seq))) 1657 (setcdr tick-seq (delq msg (cdr tick-seq)))
1713 (when (null (cdr tick-seq)) (setq mh-last-seq-used nil)) 1658 (when (null (cdr tick-seq)) (setq mh-last-seq-used nil))
1714 (mh-remove-sequence-notation msg t)) 1659 (mh-remove-sequence-notation msg (mh-colors-in-use-p)))
1715 (t 1660 (t
1716 (push msg ticked) 1661 (push msg ticked)
1717 (setq mh-last-seq-used mh-tick-seq) 1662 (setq mh-last-seq-used mh-tick-seq)
1718 (mh-add-sequence-notation msg t)))) 1663 (let ((mh-seq-list (cons `(,mh-tick-seq ,msg) mh-seq-list)))
1664 (mh-add-sequence-notation msg (mh-colors-in-use-p))))))
1719 (mh-add-msgs-to-seq ticked mh-tick-seq nil t) 1665 (mh-add-msgs-to-seq ticked mh-tick-seq nil t)
1720 (mh-undefine-sequence mh-tick-seq unticked) 1666 (mh-undefine-sequence mh-tick-seq unticked)
1721 (when mh-index-data 1667 (when mh-index-data
1722 (mh-index-add-to-sequence mh-tick-seq ticked) 1668 (mh-index-add-to-sequence mh-tick-seq ticked)
1723 (mh-index-delete-from-sequence mh-tick-seq unticked)))) 1669 (mh-index-delete-from-sequence mh-tick-seq unticked))))
1724 1670
1725 ;;;###mh-autoload 1671 ;;;###mh-autoload
1726 (defun mh-narrow-to-tick () 1672 (defun mh-narrow-to-tick ()
1727 "Restrict display of this folder to just messages in `mh-tick-seq'. 1673 "Limit to messages in `mh-tick-seq'.
1674
1728 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command." 1675 Use \\<mh-folder-mode-map>\\[mh-widen] to undo this command."
1729 (interactive) 1676 (interactive)
1730 (cond ((not mh-tick-seq) 1677 (cond ((not mh-tick-seq)
1731 (error "Enable ticking by customizing `mh-tick-seq'")) 1678 (error "Enable ticking by customizing `mh-tick-seq'"))
1732 ((null (mh-seq-msgs (mh-find-seq mh-tick-seq))) 1679 ((null (mh-seq-msgs (mh-find-seq mh-tick-seq)))
1733 (message "No messages in tick sequence")) 1680 (message "No messages in %s sequence" mh-tick-seq))
1734 (t (mh-narrow-to-seq mh-tick-seq)))) 1681 (t (mh-narrow-to-seq mh-tick-seq))))
1735
1736 1682
1737 (provide 'mh-seq) 1683 (provide 'mh-seq)
1738 1684
1739 ;;; Local Variables: 1685 ;;; Local Variables:
1740 ;;; indent-tabs-mode: nil 1686 ;;; indent-tabs-mode: nil