comparison lisp/mail/mh-speed.el @ 49120:30c4902b654d

Upgraded to MH-E version 7.1.
author Bill Wohler <wohler@newt.com>
date Wed, 08 Jan 2003 23:21:16 +0000
parents 8aaba207e44b
children
comparison
equal deleted inserted replaced
49119:938f153410ae 49120:30c4902b654d
1 ;;; mh-speed.el --- Speedbar interface for MH-E. 1 ;;; mh-speed.el --- Speedbar interface for MH-E.
2 2
3 ;; Copyright (C) 2002 Free Software Foundation, Inc. 3 ;; Copyright (C) 2002 Free Software Foundation, Inc.
4 4
5 ;; Author: Bill Wohler <wohler@newt.com> 5 ;; Author: Satyaki Das <satyaki@theforce.stanford.edu>
6 ;; Maintainer: Bill Wohler <wohler@newt.com> 6 ;; Maintainer: Bill Wohler <wohler@newt.com>
7 ;; Keywords: mail 7 ;; Keywords: mail
8 ;; See: mh-e.el 8 ;; See: mh-e.el
9 9
10 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
29 29
30 ;; Speedbar support for MH-E package. 30 ;; Speedbar support for MH-E package.
31 31
32 ;;; Change Log: 32 ;;; Change Log:
33 33
34 ;; $Id: mh-speed.el,v 1.26 2002/11/13 19:36:00 wohler Exp $ 34 ;; $Id: mh-speed.el,v 1.34 2003/01/07 21:15:20 satyaki Exp $
35 35
36 ;;; Code: 36 ;;; Code:
37 37
38 ;; Requires 38 ;; Requires
39 (require 'cl) 39 (require 'cl)
40 (require 'mh-utils)
41 (require 'mh-e) 40 (require 'mh-e)
42 (require 'speedbar) 41 (require 'speedbar)
43
44 ;; Autoloads
45 (autoload 'mh-index-goto-nearest-msg "mh-index")
46 (autoload 'mh-index-parse-folder "mh-index")
47 (autoload 'mh-visit-folder "mh-e")
48
49 ;; User customizable
50 (defcustom mh-large-folder 200
51 "The number of messages that indicates a large folder.
52 If the number of messages in a folder exceeds this value, confirmation is
53 required when the folder is visited from the speedbar."
54 :type 'integer
55 :group 'mh)
56
57 (defcustom mh-speed-flists-interval 60
58 "Time between calls to flists in seconds.
59 If 0, flists is not called repeatedly."
60 :type 'integer
61 :group 'mh)
62
63 (defcustom mh-speed-run-flists-flag t
64 "Non-nil means flists is used.
65 If non-nil, flists is executed every `mh-speed-flists-interval' seconds to
66 update the display of the number of unseen and total messages in each folder.
67 If resources are limited, this can be set to nil and the speedbar display can
68 be updated manually with the \\[mh-speed-flists] command."
69 :type 'boolean
70 :group 'mh)
71
72 (defface mh-speedbar-folder-face
73 '((((class color) (background light))
74 (:foreground "blue4"))
75 (((class color) (background dark))
76 (:foreground "light blue")))
77 "Face used for folders in the speedbar buffer."
78 :group 'mh)
79
80 (defface mh-speedbar-selected-folder-face
81 '((((class color) (background light))
82 (:foreground "red" :underline t))
83 (((class color) (background dark))
84 (:foreground "red" :underline t))
85 (t (:underline t)))
86 "Face used for the current folder."
87 :group 'mh)
88
89 (defface mh-speedbar-folder-with-unseen-messages-face
90 '((t (:inherit mh-speedbar-folder-face :bold t)))
91 "Face used for folders in the speedbar buffer which have unread messages."
92 :group 'mh)
93
94 (defface mh-speedbar-selected-folder-with-unseen-messages-face
95 '((t (:inherit mh-speedbar-selected-folder-face :bold t)))
96 "Face used for the current folder when it has unread messages."
97 :group 'mh)
98 42
99 ;; Global variables 43 ;; Global variables
100 (defvar mh-speed-refresh-flag nil) 44 (defvar mh-speed-refresh-flag nil)
101 (defvar mh-speed-last-selected-folder nil) 45 (defvar mh-speed-last-selected-folder nil)
102 (defvar mh-speed-folder-map (make-hash-table :test #'equal)) 46 (defvar mh-speed-folder-map (make-hash-table :test #'equal))
114 (copy-tree speedbar-stealthy-function-list)) 58 (copy-tree speedbar-stealthy-function-list))
115 (push 'mh-speed-stealth-update 59 (push 'mh-speed-stealth-update
116 (cdr (assoc "files" speedbar-stealthy-function-list)))) 60 (cdr (assoc "files" speedbar-stealthy-function-list))))
117 61
118 ;; Functions called by speedbar to initialize display... 62 ;; Functions called by speedbar to initialize display...
63 ;;;###mh-autoload
119 (defun mh-folder-speedbar-buttons (buffer) 64 (defun mh-folder-speedbar-buttons (buffer)
120 "Interface function to create MH-E speedbar buffer. 65 "Interface function to create MH-E speedbar buffer.
121 BUFFER is the MH-E buffer for which the speedbar buffer is to be created." 66 BUFFER is the MH-E buffer for which the speedbar buffer is to be created."
122 (unless (get-text-property (point-min) 'mh-level) 67 (unless (get-text-property (point-min) 'mh-level)
123 (erase-buffer) 68 (erase-buffer)
132 `(mh-folder nil mh-expanded nil mh-children-p t mh-level 0)) 77 `(mh-folder nil mh-expanded nil mh-children-p t mh-level 0))
133 (mh-speed-stealth-update t) 78 (mh-speed-stealth-update t)
134 (when mh-speed-run-flists-flag 79 (when mh-speed-run-flists-flag
135 (mh-speed-flists nil)))) 80 (mh-speed-flists nil))))
136 81
82 ;;;###mh-autoload
137 (defalias 'mh-show-speedbar-buttons 'mh-folder-speedbar-buttons) 83 (defalias 'mh-show-speedbar-buttons 'mh-folder-speedbar-buttons)
138 (defalias 'mh-index-folder-speedbar-buttons 'mh-folder-speedbar-buttons) 84 ;;;###mh-autoload
139 (defalias 'mh-index-show-speedbar-buttons 'mh-folder-speedbar-buttons)
140 (defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons) 85 (defalias 'mh-letter-speedbar-buttons 'mh-folder-speedbar-buttons)
141 86
142 ;; Keymaps for speedbar... 87 ;; Keymaps for speedbar...
143 (defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap) 88 (defvar mh-folder-speedbar-key-map (speedbar-make-specialized-keymap)
144 "Specialized speedbar keymap for MH-E buffers.") 89 "Specialized speedbar keymap for MH-E buffers.")
145 (gnus-define-keys mh-folder-speedbar-key-map 90 (gnus-define-keys mh-folder-speedbar-key-map
146 "+" mh-speed-expand-folder 91 "+" mh-speed-expand-folder
147 "-" mh-speed-contract-folder 92 "-" mh-speed-contract-folder
148 "\r" mh-speed-view 93 "\r" mh-speed-view
149 "f" mh-speed-flists 94 "f" mh-speed-flists
150 "i" mh-speed-invalidate-map) 95 "i" mh-speed-invalidate-map)
151 96
152 (defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map) 97 (defvar mh-show-speedbar-key-map mh-folder-speedbar-key-map)
153 (defvar mh-index-folder-speedbar-key-map mh-folder-speedbar-key-map)
154 (defvar mh-index-show-speedbar-key-map mh-folder-speedbar-key-map)
155 (defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map) 98 (defvar mh-letter-speedbar-key-map mh-folder-speedbar-key-map)
156 99
157 ;; Menus for speedbar... 100 ;; Menus for speedbar...
158 (defvar mh-folder-speedbar-menu-items 101 (defvar mh-folder-speedbar-menu-items
159 '(["Visit Folder" mh-speed-view 102 '(["Visit Folder" mh-speed-view
169 ["Run Flists" mh-speed-flists t] 112 ["Run Flists" mh-speed-flists t]
170 ["Invalidate cached folders" mh-speed-invalidate-map t]) 113 ["Invalidate cached folders" mh-speed-invalidate-map t])
171 "Extra menu items for speedbar.") 114 "Extra menu items for speedbar.")
172 115
173 (defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items) 116 (defvar mh-show-speedbar-menu-items mh-folder-speedbar-menu-items)
174 (defvar mh-index-folder-speedbar-menu-items mh-folder-speedbar-menu-items)
175 (defvar mh-index-show-speedbar-menu-items mh-folder-speedbar-menu-items)
176 (defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items) 117 (defvar mh-letter-speedbar-menu-items mh-folder-speedbar-menu-items)
177 118
178 (defmacro mh-speed-select-attached-frame () 119 (defmacro mh-speed-select-attached-frame ()
179 "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4." 120 "Compatibility macro to handle speedbar versions 0.11a and 0.14beta4."
180 (cond ((fboundp 'dframe-select-attached-frame) 121 (cond ((fboundp 'dframe-select-attached-frame)
191 Otherwise you get the disconcerting behavior of folders popping open on their 132 Otherwise you get the disconcerting behavior of folders popping open on their
192 own when you are trying to navigate around in the speedbar buffer. 133 own when you are trying to navigate around in the speedbar buffer.
193 134
194 The update is always carried out if FORCE is non-nil." 135 The update is always carried out if FORCE is non-nil."
195 (let* ((lastf (selected-frame)) 136 (let* ((lastf (selected-frame))
196 (newcf (save-excursion 137 (newcf (save-excursion
197 (mh-speed-select-attached-frame) 138 (mh-speed-select-attached-frame)
198 (prog1 (mh-speed-extract-folder-name (buffer-name)) 139 (prog1 (mh-speed-extract-folder-name (buffer-name))
199 (select-frame lastf)))) 140 (select-frame lastf))))
200 (lastb (current-buffer)) 141 (lastb (current-buffer))
201 (case-fold-search t)) 142 (case-fold-search t))
202 (when (or force 143 (when (or force
203 (and mh-speed-refresh-flag (not (eq lastf speedbar-frame))) 144 (and mh-speed-refresh-flag (not (eq lastf speedbar-frame)))
204 (and (stringp newcf) 145 (and (stringp newcf)
205 (equal (substring newcf 0 1) "+") 146 (equal (substring newcf 0 1) "+")
206 (not (equal newcf mh-speed-last-selected-folder)))) 147 (not (equal newcf mh-speed-last-selected-folder))))
269 The function will expand out parent folders of FOLDER if needed." 210 The function will expand out parent folders of FOLDER if needed."
270 (let ((prefix folder) 211 (let ((prefix folder)
271 (suffix-list ()) 212 (suffix-list ())
272 (last-slash t)) 213 (last-slash t))
273 (while (and (not (gethash prefix mh-speed-folder-map)) last-slash) 214 (while (and (not (gethash prefix mh-speed-folder-map)) last-slash)
274 (setq last-slash (search "/" prefix :from-end t)) 215 (setq last-slash (mh-search-from-end ?/ prefix))
275 (when (integerp last-slash) 216 (when (integerp last-slash)
276 (push (substring prefix (1+ last-slash)) suffix-list) 217 (push (substring prefix (1+ last-slash)) suffix-list)
277 (setq prefix (substring prefix 0 last-slash)))) 218 (setq prefix (substring prefix 0 last-slash))))
278 (let ((prefix-position (gethash prefix mh-speed-folder-map))) 219 (let ((prefix-position (gethash prefix mh-speed-folder-map)))
279 (if prefix-position 220 (if prefix-position
304 (cond ((eq major-mode 'mh-folder-mode) 245 (cond ((eq major-mode 'mh-folder-mode)
305 mh-current-folder) 246 mh-current-folder)
306 ((eq major-mode 'mh-show-mode) 247 ((eq major-mode 'mh-show-mode)
307 (set-buffer mh-show-folder-buffer) 248 (set-buffer mh-show-folder-buffer)
308 mh-current-folder) 249 mh-current-folder)
309 ((eq major-mode 'mh-index-folder-mode) 250 ((eq major-mode 'mh-letter-mode)
310 (save-excursion
311 (mh-index-goto-nearest-msg)
312 (mh-index-parse-folder)))
313 ((or (eq major-mode 'mh-index-show-mode)
314 (eq major-mode 'mh-letter-mode))
315 (when (string-match mh-user-path buffer-file-name) 251 (when (string-match mh-user-path buffer-file-name)
316 (let* ((rel-path (substring buffer-file-name (match-end 0))) 252 (let* ((rel-path (substring buffer-file-name (match-end 0)))
317 (directory-end (search "/" rel-path :from-end t))) 253 (directory-end (mh-search-from-end ?/ rel-path)))
318 (when directory-end 254 (when directory-end
319 (format "+%s" (substring rel-path 0 directory-end))))))))) 255 (format "+%s" (substring rel-path 0 directory-end)))))))))
320 256
321 (defun mh-speed-add-buttons (folder level) 257 (defun mh-speed-add-buttons (folder level)
322 "Add speedbar button for FOLDER which is at indented by LEVEL amount." 258 "Add speedbar button for FOLDER which is at indented by LEVEL amount."
345 (setf (gethash folder-name mh-speed-folder-map) 281 (setf (gethash folder-name mh-speed-folder-map)
346 (set-marker (make-marker) (1+ (line-beginning-position)))) 282 (set-marker (make-marker) (1+ (line-beginning-position))))
347 (add-text-properties 283 (add-text-properties
348 (line-beginning-position) (1+ (line-beginning-position)) 284 (line-beginning-position) (1+ (line-beginning-position))
349 `(mh-folder ,folder-name 285 `(mh-folder ,folder-name
350 mh-expanded nil 286 mh-expanded nil
351 mh-children-p ,(not (not (cdr f))) 287 mh-children-p ,(not (not (cdr f)))
352 ,@(if counts `(mh-count (,(car counts) . ,(cdr counts))) ()) 288 ,@(if counts `(mh-count
353 mh-level ,level)))))) 289 (,(car counts) . ,(cdr counts))) ())
290 mh-level ,level))))))
354 folder-list))) 291 folder-list)))
355 292
293 ;;;###mh-autoload
356 (defun mh-speed-toggle (&rest args) 294 (defun mh-speed-toggle (&rest args)
357 "Toggle the display of child folders. 295 "Toggle the display of child folders.
358 The otional ARGS are ignored and there for compatibilty with speedbar." 296 The otional ARGS are ignored and there for compatibilty with speedbar."
359 (interactive) 297 (interactive)
360 (declare (ignore args)) 298 (declare (ignore args))
391 `(mh-expanded t))))))) 329 `(mh-expanded t)))))))
392 330
393 (defalias 'mh-speed-expand-folder 'mh-speed-toggle) 331 (defalias 'mh-speed-expand-folder 'mh-speed-toggle)
394 (defalias 'mh-speed-contract-folder 'mh-speed-toggle) 332 (defalias 'mh-speed-contract-folder 'mh-speed-toggle)
395 333
396 (defun mh-speed-folder-size () 334 ;;;###mh-autoload
397 "Find folder size if folder on current line."
398 (let ((folder (get-text-property (line-beginning-position) 'mh-folder)))
399 (or (cdr (get-text-property (line-beginning-position) 'mh-count))
400 (and (null folder) 0)
401 (with-temp-buffer
402 (call-process (expand-file-name "flist" mh-progs) nil t nil
403 "-norecurse" folder)
404 (goto-char (point-min))
405 (unless (re-search-forward "out of " (line-end-position) t)
406 (error "Call to flist failed on folder %s" folder))
407 (car (read-from-string
408 (buffer-substring-no-properties (point)
409 (line-end-position))))))))
410
411 (defun mh-speed-view (&rest args) 335 (defun mh-speed-view (&rest args)
412 "View folder on current line. 336 "View folder on current line.
413 Optional ARGS are ignored." 337 Optional ARGS are ignored."
414 (interactive) 338 (interactive)
415 (declare (ignore args)) 339 (declare (ignore args))
416 (let* ((folder (get-text-property (line-beginning-position) 'mh-folder)) 340 (let* ((folder (get-text-property (line-beginning-position) 'mh-folder))
417 (range 341 (range (and (stringp folder) (mh-read-msg-range folder))))
418 (cond ((save-excursion
419 (beginning-of-line)
420 (re-search-forward "([1-9][0-9]*/[0-9]+)"
421 (line-end-position) t))
422 mh-unseen-seq)
423 ((> (mh-speed-folder-size) mh-large-folder)
424 (let* ((size (mh-speed-folder-size))
425 (prompt
426 (format "How many messages from %s (default: %s): "
427 folder size))
428 (in (read-string prompt nil nil
429 (number-to-string size)))
430 (result (car (ignore-errors (read-from-string in)))))
431 (cond ((null result) (format "last:%s" size))
432 ((numberp result) (format "last:%s" result))
433 (t (format "%s" result)))))
434 (t nil))))
435 (when (stringp folder) 342 (when (stringp folder)
436 (speedbar-with-attached-buffer 343 (speedbar-with-attached-buffer
437 (mh-visit-folder folder range) 344 (mh-visit-folder folder range)
438 (delete-other-windows))))) 345 (delete-other-windows)))))
439 346
461 (results ())) 368 (results ()))
462 (with-temp-buffer 369 (with-temp-buffer
463 (apply #'call-process arg-list) 370 (apply #'call-process arg-list)
464 (goto-char (point-min)) 371 (goto-char (point-min))
465 (while (not (and (eolp) (bolp))) 372 (while (not (and (eolp) (bolp)))
466 (let ((folder-end (or (search-forward "+ " (line-end-position) t) 373 (goto-char (line-end-position))
467 (search-forward " " (line-end-position) t)))) 374 (let ((has-pos (search-backward " has " (line-beginning-position) t)))
468 (when (integerp folder-end) 375 (when (integerp has-pos)
469 (let ((name (buffer-substring (line-beginning-position) 376 (while (or (equal (char-after has-pos) ? )
470 (match-beginning 0)))) 377 (equal (char-after has-pos) ?+))
378 (decf has-pos))
379 (incf has-pos)
380 (let ((name (buffer-substring (line-beginning-position) has-pos)))
471 (let ((first-char (substring name 0 1))) 381 (let ((first-char (substring name 0 1)))
472 (unless (or (string-equal first-char ".") 382 (unless (or (string-equal first-char ".")
473 (string-equal first-char "#") 383 (string-equal first-char "#")
474 (string-equal first-char ",")) 384 (string-equal first-char ","))
475 (push 385 (push
476 (cons name 386 (cons name
477 (search-forward "(others)" (line-end-position) t)) 387 (search-forward "(others)" (line-end-position) t))
478 results))))) 388 results)))))
479 (forward-line 1)))) 389 (forward-line 1))))
480 (setq results (nreverse results)) 390 (setq results (nreverse results))
481 (when (stringp folder) 391 (when (stringp folder)
482 (setq results (cdr results)) 392 (setq results (cdr results))
483 (let ((folder-name-len (length (format "%s/" (substring folder 1))))) 393 (let ((folder-name-len (length (format "%s/" (substring folder 1)))))
485 (cons (substring (car f) folder-name-len) 395 (cons (substring (car f) folder-name-len)
486 (cdr f))) 396 (cdr f)))
487 results)))) 397 results))))
488 results)) 398 results))
489 399
400 ;;;###mh-autoload
490 (defun mh-speed-flists (force) 401 (defun mh-speed-flists (force)
491 "Execute flists -recurse and update message counts. 402 "Execute flists -recurse and update message counts.
492 If FORCE is non-nil the timer is reset." 403 If FORCE is non-nil the timer is reset."
493 (interactive (list t)) 404 (interactive (list t))
494 (when force 405 (when force
507 (unless (and (processp mh-speed-flists-process) 418 (unless (and (processp mh-speed-flists-process)
508 (not (eq (process-status mh-speed-flists-process) 419 (not (eq (process-status mh-speed-flists-process)
509 'exit))) 420 'exit)))
510 (setq mh-speed-flists-process 421 (setq mh-speed-flists-process
511 (start-process (expand-file-name "flists" mh-progs) nil 422 (start-process (expand-file-name "flists" mh-progs) nil
512 "flists" "-recurse")) 423 "flists" "-recurse"
424 "-sequence" (symbol-name mh-unseen-seq)))
513 (set-process-filter mh-speed-flists-process 425 (set-process-filter mh-speed-flists-process
514 'mh-speed-parse-flists-output))))))) 426 'mh-speed-parse-flists-output)))))))
515 427
516 ;; Copied from mh-make-folder-list-filter... 428 ;; Copied from mh-make-folder-list-filter...
517 (defun mh-speed-parse-flists-output (process output) 429 (defun mh-speed-parse-flists-output (process output)
525 (while (setq line-end (string-match "\n" output position)) 437 (while (setq line-end (string-match "\n" output position))
526 (setq line (format "%s%s" 438 (setq line (format "%s%s"
527 mh-speed-partial-line 439 mh-speed-partial-line
528 (substring output position line-end)) 440 (substring output position line-end))
529 mh-speed-partial-line "") 441 mh-speed-partial-line "")
530 (when (string-match "+? " line) 442 (multiple-value-setq (folder unseen total)
531 (setq folder (format "+%s" (subseq line 0 (match-beginning 0)))) 443 (mh-parse-flist-output-line line))
532 (when (string-match " has " line) 444 (when (and folder unseen total)
533 (setq unseen (car (read-from-string line (match-end 0)))) 445 (setf (gethash folder mh-speed-flists-cache) (cons unseen total))
534 (when (string-match "; out of " line) 446 (save-excursion
535 (setq total (car (read-from-string line (match-end 0)))) 447 (when (buffer-live-p (get-buffer speedbar-buffer))
536 (setf (gethash folder mh-speed-flists-cache) 448 (set-buffer speedbar-buffer)
537 (cons unseen total)) 449 (speedbar-with-writable
538 (save-excursion 450 (when (get-text-property (point-min) 'mh-level)
539 (when (buffer-live-p (get-buffer speedbar-buffer)) 451 (let ((pos (gethash folder mh-speed-folder-map))
540 (set-buffer speedbar-buffer) 452 face)
541 (speedbar-with-writable 453 (when pos
542 (when (get-text-property (point-min) 'mh-level) 454 (goto-char pos)
543 (let ((pos (gethash folder mh-speed-folder-map)) 455 (goto-char (line-beginning-position))
544 face) 456 (cond
545 (when pos 457 ((null (get-text-property (point) 'mh-count))
546 (goto-char pos) 458 (goto-char (line-end-position))
547 (goto-char (line-beginning-position)) 459 (setq face (get-text-property (1- (point)) 'face))
548 (cond 460 (insert (format " (%s/%s)" unseen total))
549 ((null (get-text-property (point) 'mh-count)) 461 (mh-speed-highlight 'unknown face)
550 (goto-char (line-end-position)) 462 (goto-char (line-beginning-position))
551 (setq face (get-text-property (1- (point)) 463 (add-text-properties (point) (1+ (point))
552 'face)) 464 `(mh-count (,unseen . ,total))))
553 (insert (format " (%s/%s)" unseen total)) 465 ((not (equal (get-text-property (point) 'mh-count)
554 (mh-speed-highlight 'unknown face) 466 (cons unseen total)))
555 (goto-char (line-beginning-position)) 467 (goto-char (line-end-position))
556 (add-text-properties 468 (setq face (get-text-property (1- (point)) 'face))
557 (point) (1+ (point)) 469 (re-search-backward " " (line-beginning-position) t)
558 `(mh-count (,unseen . ,total)))) 470 (delete-region (point) (line-end-position))
559 ((not 471 (insert (format " (%s/%s)" unseen total))
560 (equal (get-text-property (point) 'mh-count) 472 (mh-speed-highlight 'unknown face)
561 (cons unseen total))) 473 (goto-char (line-beginning-position))
562 (goto-char (line-end-position)) 474 (add-text-properties
563 (setq face (get-text-property (1- (point)) 475 (point) (1+ (point))
564 'face)) 476 `(mh-count (,unseen . ,total))))))))))))
565 (re-search-backward
566 " " (line-beginning-position) t)
567 (delete-region (point) (line-end-position))
568 (insert (format " (%s/%s)" unseen total))
569 (mh-speed-highlight 'unknown face)
570 (goto-char (line-beginning-position))
571 (add-text-properties
572 (point) (1+ (point))
573 `(mh-count (,unseen . ,total))))))))))))))
574 (setq position (1+ line-end))) 477 (setq position (1+ line-end)))
575 (set-match-data prevailing-match-data)) 478 (set-match-data prevailing-match-data))
576 (setq mh-speed-partial-line (subseq output position)))) 479 (setq mh-speed-partial-line (substring output position))))
577 480
481 ;;;###mh-autoload
578 (defun mh-speed-invalidate-map (folder) 482 (defun mh-speed-invalidate-map (folder)
579 "Remove FOLDER from various optimization caches." 483 "Remove FOLDER from various optimization caches."
580 (interactive (list "")) 484 (interactive (list ""))
581 (save-excursion 485 (save-excursion
582 (set-buffer speedbar-buffer) 486 (set-buffer speedbar-buffer)
583 (let* ((speedbar-update-flag nil) 487 (let* ((speedbar-update-flag nil)
584 (last-slash (search "/" folder :from-end t)) 488 (last-slash (mh-search-from-end ?/ folder))
585 (parent (if last-slash (substring folder 0 last-slash) nil)) 489 (parent (if last-slash (substring folder 0 last-slash) nil))
586 (parent-position (gethash parent mh-speed-folder-map)) 490 (parent-position (gethash parent mh-speed-folder-map))
587 (parent-change nil)) 491 (parent-change nil))
588 (remhash parent mh-speed-folders-cache) 492 (remhash parent mh-speed-folders-cache)
589 (remhash folder mh-speed-folders-cache) 493 (remhash folder mh-speed-folders-cache)
613 (setq mh-speed-last-selected-folder nil) 517 (setq mh-speed-last-selected-folder nil)
614 (setq mh-speed-refresh-flag t))) 518 (setq mh-speed-refresh-flag t)))
615 (when (equal folder "") 519 (when (equal folder "")
616 (clrhash mh-speed-folders-cache))))) 520 (clrhash mh-speed-folders-cache)))))
617 521
522 ;;;###mh-autoload
618 (defun mh-speed-add-folder (folder) 523 (defun mh-speed-add-folder (folder)
619 "Add FOLDER since it is being created. 524 "Add FOLDER since it is being created.
620 The function invalidates the latest ancestor that is present." 525 The function invalidates the latest ancestor that is present."
621 (save-excursion 526 (save-excursion
622 (set-buffer speedbar-buffer) 527 (set-buffer speedbar-buffer)
623 (let ((speedbar-update-flag nil) 528 (let ((speedbar-update-flag nil)
624 (last-slash (search "/" folder :from-end t)) 529 (last-slash (mh-search-from-end ?/ folder))
625 (ancestor folder) 530 (ancestor folder)
626 (ancestor-pos nil)) 531 (ancestor-pos nil))
627 (block while-loop 532 (block while-loop
628 (while last-slash 533 (while last-slash
629 (setq ancestor (substring ancestor 0 last-slash)) 534 (setq ancestor (substring ancestor 0 last-slash))
630 (setq ancestor-pos (gethash ancestor mh-speed-folder-map)) 535 (setq ancestor-pos (gethash ancestor mh-speed-folder-map))
631 (when ancestor-pos 536 (when ancestor-pos
632 (return-from while-loop)) 537 (return-from while-loop))
633 (setq last-slash (search "/" ancestor :from-end t)))) 538 (setq last-slash (mh-search-from-end ?/ ancestor))))
634 (unless ancestor-pos (setq ancestor nil)) 539 (unless ancestor-pos (setq ancestor nil))
635 (goto-char (or ancestor-pos (gethash nil mh-speed-folder-map))) 540 (goto-char (or ancestor-pos (gethash nil mh-speed-folder-map)))
636 (speedbar-with-writable 541 (speedbar-with-writable
637 (mh-speedbar-change-expand-button-char ?+) 542 (mh-speedbar-change-expand-button-char ?+)
638 (add-text-properties 543 (add-text-properties
648 (defun mh-speedbar-change-expand-button-char (char) 553 (defun mh-speedbar-change-expand-button-char (char)
649 "Change the expansion button character to CHAR for the current line." 554 "Change the expansion button character to CHAR for the current line."
650 (save-excursion 555 (save-excursion
651 (beginning-of-line) 556 (beginning-of-line)
652 (if (re-search-forward "\\[.\\]" (line-end-position) t) 557 (if (re-search-forward "\\[.\\]" (line-end-position) t)
653 (speedbar-with-writable 558 (speedbar-with-writable
654 (backward-char 2) 559 (backward-char 2)
655 (delete-char 1) 560 (delete-char 1)
656 (insert-char char 1 t) 561 (insert-char char 1 t)
657 (put-text-property (point) (1- (point)) 'invisible nil) 562 (put-text-property (point) (1- (point)) 'invisible nil)
658 ;; make sure we fix the image on the text here. 563 ;; make sure we fix the image on the text here.
659 (speedbar-insert-image-button-maybe (- (point) 2) 3))))) 564 (speedbar-insert-image-button-maybe (- (point) 2) 3)))))
660 565
661 (provide 'mh-speed) 566 (provide 'mh-speed)
662 567
663 ;;; Local Variables: 568 ;;; Local Variables:
569 ;;; indent-tabs-mode: nil
664 ;;; sentence-end-double-space: nil 570 ;;; sentence-end-double-space: nil
665 ;;; End: 571 ;;; End:
666 572
667 ;;; mh-speed.el ends here 573 ;;; mh-speed.el ends here