(encode-mime-charset-region (point-min) (point-max) mime-charset))
(as-binary-output-file
(write-region (point-min) (point-max) filename nil 'no-msg)))
- (message (format "%s is not writable." filename)))))
+ (message "%s is not writable." filename))))
(defun elmo-object-save (filename object &optional mime-charset)
"Save OBJECT to the file specified by FILENAME.
(concat field "(2) Search by") default)
")"))
((string-match "Since\\|Before" field)
- (concat (downcase field) ":"
- (completing-read (format "Value for '%s': " field)
- (mapcar (function
- (lambda (x)
- (list (format "%s" (car x)))))
- elmo-date-descriptions))))
+ (let ((default (format-time-string "%Y-%m-%d")))
+ (setq value (completing-read
+ (format "Value for '%s' [%s]: " field default)
+ (mapcar (function
+ (lambda (x)
+ (list (format "%s" (car x)))))
+ elmo-date-descriptions)))
+ (concat (downcase field) ":"
+ (if (equal value "") default value))))
(t
(setq value (read-from-minibuffer (format "Value for '%s': " field)))
(unless (string-match (concat "^" elmo-condition-atom-regexp "$")
;; time ::= "yesterday" / "lastweek" / "lastmonth" / "lastyear" /
;; number SPACE* "daysago" /
;; number "-" month "-" number ; ex. 10-May-2000
+;; number "-" number "-" number ; ex. 2000-05-10
;; number ::= [0-9]+
;; month ::= "Jan" / "Feb" / "Mar" / "Apr" / "May" / "Jun" /
;; "Jul" / "Aug" / "Sep" / "Oct" / "Nov" / "Dec"
(looking-at "lastmonth") (looking-at "lastyear")
(looking-at "[0-9]+ *daysago")
(looking-at "[0-9]+-[A-Za-z]+-[0-9]+")
+ (looking-at "[0-9]+-[0-9]+-[0-9]+")
(looking-at "[0-9]+")
(looking-at elmo-condition-atom-regexp))
(prog1 (elmo-match-buffer 0)
lst)
(defun elmo-list-insert (list element after)
- "Insert an ELEMENT to the LIST, just after AFTER."
- (let ((li list)
- (curn 0)
- p pn)
- (while li
- (if (eq (car li) after)
- (setq p li pn curn li nil)
- (incf curn))
- (setq li (cdr li)))
- (if pn
- (setcdr (nthcdr pn list) (cons element (cdr p)))
+ (let* ((match (memq after list))
+ (rest (and match (cdr (memq after list)))))
+ (if match
+ (progn
+ (setcdr match (list element))
+ (nconc list rest))
(nconc list (list element)))))
(defun elmo-string-partial-p (string)
(defun elmo-passwd-alist-load ()
(save-excursion
(let ((filename (expand-file-name elmo-passwd-alist-file-name
- elmo-msgdb-dir))
+ elmo-msgdb-directory))
(tmp-buffer (get-buffer-create " *elmo-passwd-alist-tmp*"))
insert-file-contents-pre-hook ; To avoid autoconv-xmas...
insert-file-contents-post-hook
(interactive)
(save-excursion
(let ((filename (expand-file-name elmo-passwd-alist-file-name
- elmo-msgdb-dir))
+ elmo-msgdb-directory))
(tmp-buffer (get-buffer-create " *elmo-passwd-alist-tmp*")))
(set-buffer tmp-buffer)
(erase-buffer)
(write-region (point-min) (point-max)
filename nil 'no-msg)
(set-file-modes filename 384))
- (message (format "%s is not writable." filename)))
+ (message "%s is not writable." filename))
(kill-buffer tmp-buffer))))
(defun elmo-get-passwd (key)
(setq result (+ result (or (elmo-disk-usage (car files)) 0)))
(setq files (cdr files)))
result)
- (float (nth 7 file-attr))))))
+ (float (nth 7 file-attr)))
+ 0)))
(defun elmo-get-last-accessed-time (path &optional dir)
"Return the last accessed time of PATH."
(setq last-modified (+ (* (nth 0 last-modified)
(float 65536)) (nth 1 last-modified)))))
-(defun elmo-make-directory (path)
+(defun elmo-make-directory (path &optional mode)
"Create directory recursively."
(let ((parent (directory-file-name (file-name-directory path))))
(if (null (file-directory-p parent))
(elmo-make-directory parent))
(make-directory path)
- (if (string= path (expand-file-name elmo-msgdb-dir))
- (set-file-modes path (+ (* 64 7) (* 8 0) 0))))) ; chmod 0700
+ (set-file-modes path (or mode
+ (+ (* 64 7) (* 8 0) 0))))) ; chmod 0700
(defun elmo-delete-directory (path &optional no-hierarchy)
"Delete directory recursively."
(unless hierarchy
(delete-directory path)))))
+(defun elmo-delete-match-files (path regexp &optional remove-if-empty)
+ "Delete directory files specified by PATH.
+If optional REMOVE-IF-EMPTY is non-nil, delete directory itself if
+the directory becomes empty after deletion."
+ (when (stringp path) ; nil is not permitted.
+ (dolist (file (directory-files path t regexp))
+ (delete-file file))
+ (if remove-if-empty
+ (ignore-errors
+ (delete-directory path) ; should be removed if empty.
+ ))))
+
(defun elmo-list-filter (l1 l2)
"L1 is filter."
(if (eq l1 t)
(setq clist2 (delq (car list1) clist2))
(setq list1 (cdr list1)))
(if mes
- (message (concat mes "done.")))
+ (message (concat mes "done")))
(list clist1 clist2)))
(defun elmo-list-bigger-diff (list1 list2 &optional mes)
(setq l1 (cdr l1)))
(cons diff1 (list l2)))))
+(defmacro elmo-filter-condition-p (filter)
+ `(or (vectorp ,filter) (consp ,filter)))
+
(defmacro elmo-filter-type (filter)
(` (aref (, filter) 0)))
(length (memq number number-list)))
(string-to-int (elmo-filter-value condition)))))
((string= (elmo-filter-key condition) "since")
- (let ((date (elmo-date-get-datevec (elmo-filter-value condition))))
+ (let ((field-date (elmo-date-make-sortable-string
+ (timezone-fix-time
+ (std11-field-body "date")
+ (current-time-zone) nil)))
+ (specified-date (elmo-date-make-sortable-string
+ (elmo-date-get-datevec
+ (elmo-filter-value condition)))))
(setq result
- (string<
- (timezone-make-sortable-date (aref date 0)
- (aref date 1)
- (aref date 2)
- (timezone-make-time-string
- (aref date 3)
- (aref date 4)
- (aref date 5)))
- (timezone-make-date-sortable (std11-field-body "date"))))))
+ (or (string= field-date specified-date)
+ (string< specified-date field-date)))))
((string= (elmo-filter-key condition) "before")
- (let ((date (elmo-date-get-datevec (elmo-filter-value condition))))
- (setq result
- (string<
- (timezone-make-date-sortable (std11-field-body "date"))
- (timezone-make-sortable-date (aref date 0)
- (aref date 1)
- (aref date 2)
- (timezone-make-time-string
- (aref date 3)
- (aref date 4)
- (aref date 5)))))))
+ (setq result
+ (string<
+ (elmo-date-make-sortable-string
+ (timezone-fix-time
+ (std11-field-body "date")
+ (current-time-zone) nil))
+ (elmo-date-make-sortable-string
+ (elmo-date-get-datevec
+ (elmo-filter-value condition))))))
((string= (elmo-filter-key condition) "body")
(and (re-search-forward "^$" nil t) ; goto body
(setq result (search-forward (elmo-filter-value condition)
(cond
((string= (elmo-filter-key condition) "last")
(setq result (<= (length (memq number number-list))
- (string-to-int (elmo-filter-value condition)))))
+ (string-to-int (elmo-filter-value condition))))
+ (if (eq (elmo-filter-type condition) 'unmatch)
+ (setq result (not result))))
((string= (elmo-filter-key condition) "first")
(setq result (< (- (length number-list)
(length (memq number number-list)))
- (string-to-int (elmo-filter-value condition)))))
+ (string-to-int (elmo-filter-value condition))))
+ (if (eq (elmo-filter-type condition) 'unmatch)
+ (setq result (not result))))
(t
(elmo-set-work-buf
(as-binary-input-file (insert-file-contents file))
(setq result
(elmo-buffer-field-primitive-condition-match
condition number number-list)))))
- (if (eq (elmo-filter-type condition) 'unmatch)
- (setq result (not result)))
result))
(defun elmo-file-field-condition-match (file condition number number-list)
file (nth 2 condition) number number-list)))))
(defmacro elmo-get-hash-val (string hashtable)
- (let ((sym (list 'intern-soft string hashtable)))
- (list 'if (list 'boundp sym)
- (list 'symbol-value sym))))
+ `(and (stringp ,string)
+ (let ((sym (intern-soft ,string ,hashtable)))
+ (if (boundp sym)
+ (symbol-value sym)))))
(defmacro elmo-set-hash-val (string value hashtable)
(list 'set (list 'intern string hashtable) value))
(defsubst elmo-mime-string (string)
"Normalize MIME encoded STRING."
- (and string
- (let (str)
- (elmo-set-work-buf
- (elmo-set-buffer-multibyte default-enable-multibyte-characters)
- (setq str (eword-decode-string
- (decode-mime-charset-string string elmo-mime-charset)))
- (setq str (encode-mime-charset-string str elmo-mime-charset))
- (elmo-set-buffer-multibyte nil)
- str))))
+ (and string
+ (elmo-set-work-buf
+ (elmo-set-buffer-multibyte default-enable-multibyte-characters)
+ (setq string
+ (encode-mime-charset-string
+ (eword-decode-and-unfold-unstructured-field-body
+ string)
+ elmo-mime-charset))
+ (elmo-set-buffer-multibyte nil)
+ string)))
(defsubst elmo-collect-field (beg end downcase-field-name)
(save-excursion
(setq lst (cdr lst)))
result))
-(defun elmo-list-delete (list1 list2)
+(defun elmo-list-delete (list1 list2 &optional delete-function)
"Delete by side effect any occurrences equal to elements of LIST1 from LIST2.
Return the modified LIST2. Deletion is done with `delete'.
Write `(setq foo (elmo-list-delete bar foo))' to be sure of changing
-the value of `foo'."
+the value of `foo'.
+If optional DELETE-FUNCTION is speficied, it is used as delete procedure."
+ (setq delete-function (or delete-function 'delete))
(while list1
- (setq list2 (delete (car list1) list2))
+ (setq list2 (funcall delete-function (car list1) list2))
(setq list1 (cdr list1)))
list2)
(defun elmo-progress-clear (label)
(let ((counter (assq label elmo-progress-counter-alist)))
(when counter
- (elmo-display-progress label "" 100)
+ (elmo-display-progress label
+ (elmo-progress-counter-format counter)
+ 100)
(setq elmo-progress-counter-alist
(delq counter elmo-progress-counter-alist)))))
(defmacro elmo-string (string)
"STRING without text property."
(` (let ((obj (copy-sequence (, string))))
- (set-text-properties 0 (length obj) nil obj)
+ (and obj (set-text-properties 0 (length obj) nil obj))
obj)))
(defun elmo-flatten (list-of-list)
(setq alist (cdr alist)))
matches))
+(defun elmo-expand-newtext (newtext original)
+ (let ((len (length newtext))
+ (pos 0)
+ c expanded beg N did-expand)
+ (while (< pos len)
+ (setq beg pos)
+ (while (and (< pos len)
+ (not (= (aref newtext pos) ?\\)))
+ (setq pos (1+ pos)))
+ (unless (= beg pos)
+ (push (substring newtext beg pos) expanded))
+ (when (< pos len)
+ ;; We hit a \; expand it.
+ (setq did-expand t
+ pos (1+ pos)
+ c (aref newtext pos))
+ (if (not (or (= c ?\&)
+ (and (>= c ?1)
+ (<= c ?9))))
+ ;; \ followed by some character we don't expand.
+ (push (char-to-string c) expanded)
+ ;; \& or \N
+ (if (= c ?\&)
+ (setq N 0)
+ (setq N (- c ?0)))
+ (when (match-beginning N)
+ (push (substring original (match-beginning N) (match-end N))
+ expanded))))
+ (setq pos (1+ pos)))
+ (if did-expand
+ (apply (function concat) (nreverse expanded))
+ newtext)))
+
;;; Folder parser utils.
(defun elmo-parse-token (string &optional seps)
"Parse atom from STRING using SEPS as a string of separator char list."
(if (setq msgid (elmo-msgid-to-cache msgid))
(expand-file-name
(if section
- (format "%s/%s/%s/%s/%s"
- elmo-msgdb-dir
- elmo-cache-dirname
+ (format "%s/%s/%s/%s"
+ elmo-cache-directory
(elmo-cache-get-path-subr msgid)
msgid
section)
- (format "%s/%s/%s/%s"
- elmo-msgdb-dir
- elmo-cache-dirname
+ (format "%s/%s/%s"
+ elmo-cache-directory
(elmo-cache-get-path-subr msgid)
msgid)))))
(defun elmo-file-cache-delete (path)
"Delete a cache on PATH."
- (let (files)
- (when (file-exists-p path)
- (if (file-directory-p path)
- (progn
- (setq files (directory-files path t "^[^\\.]"))
- (while files
- (delete-file (car files))
- (setq files (cdr files)))
- (delete-directory path))
- (delete-file path)))))
+ (when (file-exists-p path)
+ (if (file-directory-p path)
+ (progn
+ (dolist (file (directory-files path t "^[^\\.]"))
+ (delete-file file))
+ (delete-directory path))
+ (delete-file path))
+ t))
(defun elmo-file-cache-exists-p (msgid)
"Returns 'section or 'entire if a cache which corresponds to MSGID exists."
;; ignore error
(error)))
+(defun elmo-file-cache-load (cache-path section)
+ "Load cache on PATH into the current buffer.
+Return t if cache is loaded successfully."
+ (condition-case nil
+ (let (cache-file)
+ (when (and cache-path
+ (if (elmo-cache-path-section-p cache-path)
+ section
+ (null section))
+ (setq cache-file (elmo-file-cache-expand-path
+ cache-path
+ section))
+ (file-exists-p cache-file))
+ (insert-file-contents-as-binary cache-file)
+ t))
+ ;; igore error
+ (error)))
+
(defun elmo-cache-path-section-p (path)
"Return non-nil when PATH is `section' cache path."
(file-directory-p path))
total beginning)
(message "Checking disk usage...")
(setq total (/ (elmo-disk-usage
- (expand-file-name
- elmo-cache-dirname elmo-msgdb-dir)) Kbytes))
+ elmo-cache-directory) Kbytes))
(setq beginning total)
(message "Checking disk usage...done")
(let ((cfl (elmo-cache-get-sorted-cache-file-list))
(defun elmo-cache-get-sorted-cache-file-list ()
(let ((dirs (directory-files
- (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
+ elmo-cache-directory
t "^[^\\.]"))
(i 0) num
elist
elmo-cache-expire-default-age)))
(int-to-string elmo-cache-expire-default-age)))
(dirs (directory-files
- (expand-file-name elmo-cache-dirname elmo-msgdb-dir)
+ elmo-cache-directory
t "^[^\\.]"))
(count 0)
curtime)
(format "%s/%s"
(elmo-cache-get-path-subr msgid)
msgid))
- (expand-file-name elmo-cache-dirname
- elmo-msgdb-dir)))))
+ elmo-cache-directory))))
;;;
;; Warnings.
-(defconst elmo-warning-buffer-name "*elmo warning*")
-
-(defun elmo-warning (&rest args)
- "Display a warning, making warning message by passing all args to `insert'."
- (with-current-buffer (get-buffer-create elmo-warning-buffer-name)
- (goto-char (point-max))
- (apply 'insert (append args '("\n")))
- (recenter 1))
- (display-buffer elmo-warning-buffer-name))
+(static-if (fboundp 'display-warning)
+ (defmacro elmo-warning (&rest args)
+ "Display a warning with `elmo' group."
+ `(display-warning 'elmo (format ,@args)))
+ (defconst elmo-warning-buffer-name "*elmo warning*")
+ (defun elmo-warning (&rest args)
+ "Display a warning. ARGS are passed to `format'."
+ (with-current-buffer (get-buffer-create elmo-warning-buffer-name)
+ (goto-char (point-max))
+ (funcall 'insert (apply 'format (append args '("\n"))))
+ (ignore-errors (recenter 1))
+ (display-buffer elmo-warning-buffer-name))))
(defvar elmo-obsolete-variable-alist nil)
(defvaralias var obsolete)
(set var (symbol-value obsolete)))
(if elmo-obsolete-variable-show-warnings
- (elmo-warning (format "%s is obsolete. Use %s instead."
- (symbol-name obsolete)
- (symbol-name var))))))
+ (elmo-warning "%s is obsolete. Use %s instead."
+ (symbol-name obsolete)
+ (symbol-name var)))))
(defun elmo-resque-obsolete-variables (&optional alist)
"Resque obsolete variables in ALIST.
(setq elmo-dop-queue
(elmo-object-load
(expand-file-name elmo-dop-queue-filename
- elmo-msgdb-dir))))
+ elmo-msgdb-directory))))
(defun elmo-dop-queue-save ()
(elmo-object-save
(expand-file-name elmo-dop-queue-filename
- elmo-msgdb-dir)
+ elmo-msgdb-directory)
elmo-dop-queue))
(require 'product)