aboutsummaryrefslogtreecommitdiffstats
path: root/_spacemacs.d/local/mu4e/mu4e-utils.el
diff options
context:
space:
mode:
Diffstat (limited to '_spacemacs.d/local/mu4e/mu4e-utils.el')
-rw-r--r--_spacemacs.d/local/mu4e/mu4e-utils.el1281
1 files changed, 0 insertions, 1281 deletions
diff --git a/_spacemacs.d/local/mu4e/mu4e-utils.el b/_spacemacs.d/local/mu4e/mu4e-utils.el
deleted file mode 100644
index f8110b5..0000000
--- a/_spacemacs.d/local/mu4e/mu4e-utils.el
+++ /dev/null
@@ -1,1281 +0,0 @@
-;;; mu4e-utils.el -- part of mu4e, the mu mail user agent
-;;
-;; Copyright (C) 2011-2016 Dirk-Jan C. Binnema
-;; Copyright (C) 2013 Tibor Simko
-
-;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
-;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
-
-;; This file is not part of GNU Emacs.
-;;
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Utility functions used in the mu4e
-
-;;; Code:
-(eval-when-compile (byte-compile-disable-warning 'cl-functions))
-(require 'cl)
-
-(eval-when-compile (require 'org nil 'noerror))
-
-(require 'mu4e-vars)
-(require 'mu4e-meta)
-(require 'mu4e-lists)
-(require 'doc-view)
-
-;; keep the byte-compiler happy
-(declare-function mu4e~proc-mkdir "mu4e-proc")
-(declare-function mu4e~proc-ping "mu4e-proc")
-(declare-function mu4e~proc-contacts "mu4e-proc")
-(declare-function mu4e~proc-kill "mu4e-proc")
-(declare-function mu4e~proc-index "mu4e-proc")
-(declare-function mu4e~proc-add "mu4e-proc")
-(declare-function mu4e~proc-mkdir "mu4e-proc")
-(declare-function mu4e~proc-running-p "mu4e-proc")
-
-(declare-function mu4e~context-autoswitch "mu4e-context")
-(declare-function mu4e-context-determine "mu4e-context")
-(declare-function mu4e-context-vars "mu4e-context")
-(declare-function show-all "org")
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; the following is taken from org.el; we copy it here since we don't want to
-;; depend on org-mode directly (it causes byte-compilation errors) TODO: a
-;; cleaner solution....
-(defconst mu4e~ts-regexp0
- (concat
- "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)"
- "\\( +[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):"
- "\\([0-9]\\{2\\}\\)\\)?\\)")
- "Regular expression matching time strings for analysis.
-This one does not require the space after the date, so it can be
-used on a string that terminates immediately after the date.")
-
-(defun mu4e-parse-time-string (s &optional nodefault)
- "Parse the standard Org-mode time string.
-This should be a lot faster than the normal `parse-time-string'.
-If time is not given, defaults to 0:00. However, with optional
-NODEFAULT, hour and minute fields will be nil if not given."
- (if (string-match mu4e~ts-regexp0 s)
- (list 0
- (if (or (match-beginning 8) (not nodefault))
- (string-to-number (or (match-string 8 s) "0")))
- (if (or (match-beginning 7) (not nodefault))
- (string-to-number (or (match-string 7 s) "0")))
- (string-to-number (match-string 4 s))
- (string-to-number (match-string 3 s))
- (string-to-number (match-string 2 s))
- nil nil nil)
- (mu4e-error "Not a standard mu4e time string: %s" s)))
-
-
-(defun mu4e-user-mail-address-p (addr)
- "If ADDR is one of user's e-mail addresses return t, nil otherwise.
-User's addresses are set in `mu4e-user-mail-address-list')."
- (when (and addr mu4e-user-mail-address-list
- (find addr mu4e-user-mail-address-list :test 'string=))
- t))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defmacro with~mu4e-context-vars (context &rest body)
- "Evaluate BODY, with variables let-bound for CONTEXT (if any).
-`funcall'."
- (declare (indent 2))
- `(let* ((vars (and ,context (mu4e-context-vars ,context))))
- (progv ;; XXX: perhaps use eval's lexical environment instead of progv?
- (mapcar (lambda(cell) (car cell)) vars)
- (mapcar (lambda(cell) (cdr cell)) vars)
- (eval ,@body))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; the standard folders can be functions too
-(defun mu4e~get-folder (foldervar msg)
- "Within the mu-context of MSG, get message folder FOLDERVAR.
-If FOLDER is a string, return it, if it is a function, evaluate
-this function with MSG as parameter (which may be `nil'), and
-return the result."
- (unless (member foldervar
- '(mu4e-sent-folder mu4e-drafts-folder
- mu4e-trash-folder mu4e-refile-folder))
- (mu4e-error "Folder must be one of mu4e-(sent|drafts|trash|refile)-folder"))
- ;; get the value with the vars for the relevants context let-bound
- (with~mu4e-context-vars (mu4e-context-determine msg nil)
- (let* ((folder (symbol-value foldervar))
- (val
- (cond
- ((stringp folder) folder)
- ((functionp folder) (funcall folder msg))
- (t (mu4e-error "unsupported type for %S" folder)))))
- (or val (mu4e-error "%S evaluates to nil" foldervar)))))
-
-(defun mu4e-get-drafts-folder (&optional msg)
- "Get the sent folder. See `mu4e-drafts-folder'."
- (mu4e~get-folder 'mu4e-drafts-folder msg))
-
-(defun mu4e-get-refile-folder (&optional msg)
- "Get the folder for refiling. See `mu4e-refile-folder'."
- (mu4e~get-folder 'mu4e-refile-folder msg))
-
-(defun mu4e-get-sent-folder (&optional msg)
- "Get the sent folder. See `mu4e-sent-folder'."
- (mu4e~get-folder 'mu4e-sent-folder msg))
-
-(defun mu4e-get-trash-folder (&optional msg)
- "Get the sent folder. See `mu4e-trash-folder'."
- (mu4e~get-folder 'mu4e-trash-folder msg))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e-remove-file-later (filename)
- "Remove FILENAME in a few seconds."
- (lexical-let ((filename filename))
- (run-at-time "10 sec" nil
- (lambda () (ignore-errors (delete-file filename))))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e-make-temp-file (ext)
- "Create a temporary file with extension EXT. The file will
-self-destruct in a few seconds, enough to open it in another
-program."
- (let ((tmpfile (make-temp-file "mu4e-" nil (concat "." ext))))
- (mu4e-remove-file-later tmpfile)
- tmpfile))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; mu4e-attachment-dir is either a string or a function that takes a filename
-;; and the mime-type as argument, either (or both) which can be nil
-(defun mu4e~get-attachment-dir (&optional fname mimetype)
- "Get the directory for saving attachments from
-`mu4e-attachment-dir' (which can be either a string or a function,
-see its docstring)."
- (let
- ((dir
- (cond
- ((stringp mu4e-attachment-dir)
- mu4e-attachment-dir)
- ((functionp mu4e-attachment-dir)
- (funcall mu4e-attachment-dir fname mimetype))
- (t
- (mu4e-error "unsupported type for mu4e-attachment-dir" )))))
- (if dir
- (expand-file-name dir)
- (mu4e-error (mu4e-error "mu4e-attachment-dir evaluates to nil")))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e~guess-maildir (path)
- "Guess the maildir for some path, or nil if cannot find it."
- (let ((idx (string-match mu4e-maildir path)))
- (when (and idx (zerop idx))
- (replace-regexp-in-string
- mu4e-maildir
- ""
- (expand-file-name
- (concat path "/../.."))))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e-create-maildir-maybe (dir)
- "Offer to create maildir DIR if it does not exist yet.
-Return t if the dir already existed, or an attempt has been made to
-create it -- we cannot be sure creation succeeded here, since this
-is done asynchronously. Otherwise, return nil. NOte, DIR has to be
-an absolute path."
- (if (and (file-exists-p dir) (not (file-directory-p dir)))
- (mu4e-error "%s exists, but is not a directory." dir))
- (cond
- ((file-directory-p dir) t)
- ((yes-or-no-p (mu4e-format "%s does not exist yet. Create now?" dir))
- (mu4e~proc-mkdir dir) t)
- (t nil)))
-
-(defun mu4e-format (frm &rest args)
- "Create [mu4e]-prefixed string based on format FRM and ARGS."
- (concat
- "[" (propertize "mu4e" 'face 'mu4e-title-face) "] "
- (apply 'format frm args)))
-
-(defun mu4e-message (frm &rest args)
- "Like `message', but prefixed with mu4e.
-If we're waiting for user-input or if there's some message in the
-echo area, don't show anything."
- (unless (or (active-minibuffer-window))
- (message "%s" (apply 'mu4e-format frm args))))
-
-(defun mu4e-index-message (frm &rest args)
- "Like `mu4e-message', but specifically for
-index-messages. Doesn't display anything if
-`mu4e-hide-index-messages' is non-nil. "
- (unless mu4e-hide-index-messages
- (apply 'mu4e-message frm args)))
-
-(defun mu4e-error (frm &rest args)
- "Create [mu4e]-prefixed error based on format FRM and ARGS.
-Does a local-exit and does not return, and raises a
-debuggable (backtrace) error."
- (mu4e-log 'error (apply 'mu4e-format frm args))
- (error "%s" (apply 'mu4e-format frm args)))
-
-;; the user-error function is only available in emacs-trunk
-(unless (fboundp 'user-error)
- (defalias 'user-error 'error))
-
-(defun mu4e-warn (frm &rest args)
- "Create [mu4e]-prefixed warning based on format FRM and ARGS.
-Does a local-exit and does not return. In emacs versions below
-24.2, the functions is the same as `mu4e-error'."
- (mu4e-log 'error (apply 'mu4e-format frm args))
- (user-error "%s" (apply 'mu4e-format frm args)))
-
-(defun mu4e~read-char-choice (prompt choices)
- "Read and return one of CHOICES, prompting for PROMPT.
-Any input that is not one of CHOICES is ignored. This mu4e's
-version of `read-char-choice', that becomes case-insentive after
-trying an exact match."
- (let ((choice) (chosen) (inhibit-quit nil))
- (while (not chosen)
- (message nil);; this seems needed...
- (setq choice (read-char-exclusive prompt))
- (setq chosen (or (member choice choices)
- (member (downcase choice) choices)
- (member (upcase choice) choices))))
- (car chosen)))
-
-(defun mu4e-read-option (prompt options)
- "Ask user for an option from a list on the input area.
-PROMPT describes a multiple-choice question to the user.
-OPTIONS describe the options, and is a list of cells describing
-particular options. Cells have the following structure:
-
- (OPTIONSTRING . RESULT)
-
-where OPTIONSTRING is a non-empty string describing the
-option. The first character of OPTIONSTRING is used as the
-shortcut, and obviously all shortcuts must be different, so you
-can prefix the string with an uniquifying character.
-
-The options are provided as a list for the user to choose from;
-user can then choose by typing CHAR. Example:
- (mu4e-read-option \"Choose an animal: \"
- '((\"Monkey\" . monkey) (\"Gnu\" . gnu) (\"xMoose\" . moose)))
-
-User now will be presented with a list: \"Choose an animal:
- [M]onkey, [G]nu, [x]Moose\".
-
-Function will return the cdr of the list element."
- (let* ((prompt (mu4e-format "%s" prompt))
- (chosen)
- (optionsstr
- (mapconcat
- (lambda (option)
- ;; try to detect old-style options, and warn
- (when (characterp (car-safe (cdr-safe option)))
- (mu4e-error
- (concat "Please use the new format for options/actions; "
- "see the manual")))
- (let* ((kar (substring (car option) 0 1))
- (val (cdr option)))
- (concat
- "[" (propertize kar 'face 'mu4e-highlight-face) "]"
- (substring (car option) 1))))
- options ", "))
- (response
- (mu4e~read-char-choice
- (concat prompt optionsstr
- " [" (propertize "C-g" 'face 'mu4e-highlight-face)
- " to cancel]")
- ;; the allowable chars
- (map 'list (lambda(elm) (string-to-char (car elm))) options)))
- (chosen
- (find-if
- (lambda (option) (eq response (string-to-char (car option))))
- options)))
- (if chosen
- (cdr chosen)
- (mu4e-warn "Unknown shortcut '%c'" response))))
-
-(defun mu4e~get-maildirs-1 (path mdir)
- "Get maildirs under path, recursively, as a list of relative paths."
- (let ((dirs)
- (dentries
- (ignore-errors
- (directory-files-and-attributes
- (concat path mdir) nil
- "^[^.]\\|\\.[^.][^.]" t))))
- (dolist (dentry dentries)
- (when (and (booleanp (cadr dentry)) (cadr dentry))
- (if (file-accessible-directory-p
- (concat mu4e-maildir "/" mdir "/" (car dentry) "/cur"))
- (setq dirs (cons (concat mdir (car dentry)) dirs)))
- (unless (member (car dentry) '("cur" "new" "tmp"))
- (setq dirs (append dirs (mu4e~get-maildirs-1 path
- (concat mdir (car dentry) "/")))))))
- dirs))
-
-(defvar mu4e-cache-maildir-list nil
- "Whether to cache the list of maildirs; set it to t if you find
-that generating the list on the fly is too slow. If you do, you
-can set `mu4e-maildir-list' to nil to force regenerating the
-cache the next time `mu4e-get-maildirs' gets called.")
-
-(defvar mu4e-maildir-list nil
- "Cached list of maildirs.")
-
-(defun mu4e-get-maildirs ()
- "Get maildirs under `mu4e-maildir', recursively, as a list of
-relative paths (ie., /archive, /sent etc.). Most of the work is
-done in `mu4e-get-maildirs-1'. Note, these results are /cached/, so
-the list of maildirs will not change until you restart mu4e."
- (unless mu4e-maildir (mu4e-error "`mu4e-maildir' is not defined"))
- (unless (and mu4e-maildir-list mu4e-cache-maildir-list)
- (setq mu4e-maildir-list
- (sort
- (append
- (when (file-accessible-directory-p
- (concat mu4e-maildir "/cur")) '("/"))
- (mu4e~get-maildirs-1 mu4e-maildir "/"))
- (lambda (s1 s2) (string< (downcase s1) (downcase s2))))))
- mu4e-maildir-list)
-
-(defun mu4e-ask-maildir (prompt)
- "Ask the user for a shortcut (using PROMPT) as defined in
-`mu4e-maildir-shortcuts', then return the corresponding folder
-name. If the special shortcut 'o' (for _o_ther) is used, or if
-`mu4e-maildir-shortcuts' is not defined, let user choose from all
-maildirs under `mu4e-maildir'."
- (let ((prompt (mu4e-format "%s" prompt)))
- (if (not mu4e-maildir-shortcuts)
- (funcall mu4e-completing-read-function prompt (mu4e-get-maildirs))
- (let* ((mlist (append mu4e-maildir-shortcuts '(("ther" . ?o))))
- (fnames
- (mapconcat
- (lambda (item)
- (concat
- "["
- (propertize (make-string 1 (cdr item))
- 'face 'mu4e-highlight-face)
- "]"
- (car item)))
- mlist ", "))
- (kar (read-char (concat prompt fnames))))
- (if (member kar '(?/ ?o)) ;; user chose 'other'?
- (funcall mu4e-completing-read-function prompt
- (mu4e-get-maildirs) nil nil "/")
- (or (car-safe
- (find-if (lambda (item) (= kar (cdr item)))
- mu4e-maildir-shortcuts))
- (mu4e-warn "Unknown shortcut '%c'" kar)))))))
-
-
-(defun mu4e-ask-maildir-check-exists (prompt)
- "Like `mu4e-ask-maildir', but check for existence of the maildir,
-and offer to create it if it does not exist yet."
- (let* ((mdir (mu4e-ask-maildir prompt))
- (fullpath (concat mu4e-maildir mdir)))
- (unless (file-directory-p fullpath)
- (and (yes-or-no-p
- (mu4e-format "%s does not exist. Create now?" fullpath))
- (mu4e~proc-mkdir fullpath)))
- mdir))
-
-
-(defstruct mu4e-bookmark
- "A mu4e bookmarl object with the following members:
-- `name': the user-visible name of the bookmark
-- `key': a single key to search for this bookmark
-- `query': the query for this bookmark. Either a literal string or a function
- that evaluates to a string."
- name ;; name/description of the bookmark
- query ;; a query (a string or a function evaluation to string)
- key ;; key to activate the bookmark
- )
-
-(defun mu4e-bookmarks ()
- "Get `mu4e-bookmarks' in the (new) format, converting from the old
-format if needed."
- (map 'list
- (lambda (item)
- (if (mu4e-bookmark-p item)
- item ;; already in the right format
- (if (and (listp item) (= (length item) 3))
- (make-mu4e-bookmark
- :name (nth 1 item)
- :query (nth 0 item)
- :key (nth 2 item))
- (mu4e-error "Invalid bookmark in mu4e-bookmarks"))))
- mu4e-bookmarks))
-
-
-(defun mu4e-ask-bookmark (prompt &optional kar)
- "Ask the user for a bookmark (using PROMPT) as defined in
-`mu4e-bookmarks', then return the corresponding query."
- (unless (mu4e-bookmarks) (mu4e-error "No bookmarks defined"))
- (let* ((prompt (mu4e-format "%s" prompt))
- (bmarks
- (mapconcat
- (lambda (bm)
- (concat
- "[" (propertize (make-string 1 (mu4e-bookmark-key bm))
- 'face 'mu4e-highlight-face)
- "]"
- (mu4e-bookmark-name bm))) (mu4e-bookmarks) ", "))
- (kar (read-char (concat prompt bmarks))))
- (mu4e-get-bookmark-query kar)))
-
-(defun mu4e-get-bookmark-query (kar)
- "Get the corresponding bookmarked query for shortcut character
-KAR, or raise an error if none is found."
- (let* ((chosen-bm
- (or (find-if
- (lambda (bm)
- (= kar (mu4e-bookmark-key bm)))
- (mu4e-bookmarks))
- (mu4e-warn "Unknown shortcut '%c'" kar)))
- (expr (mu4e-bookmark-query chosen-bm))
- (query (eval expr)))
- (if (stringp query)
- query
- (mu4e-warn "Expression must evaluate to query string ('%S')" expr))))
-
-
-(defun mu4e-bookmark-define (query name key)
- "Define a bookmark for QUERY with name NAME and
-shortcut-character KEY in the list of `mu4e-bookmarks'. This
-replaces any existing bookmark with KEY."
- (setq mu4e-bookmarks
- (remove-if
- (lambda (bm)
- (= (mu4e-bookmark-key bm) key))
- (mu4e-bookmarks)))
- (add-to-list 'mu4e-bookmarks
- (make-mu4e-bookmark
- :name name
- :query query
- :key key) t))
-
-
-;;; converting flags->string and vice-versa ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e~flags-to-string-raw (flags)
- "Convert a list of flags into a string as seen in Maildir
-message files; flags are symbols draft, flagged, new, passed,
-replied, seen, trashed and the string is the concatenation of the
-uppercased first letters of these flags, as per [1]. Other flags
-than the ones listed here are ignored.
-Also see `mu4e-flags-to-string'.
-\[1\]: http://cr.yp.to/proto/maildir.html"
- (when flags
- (let ((kar (case (car flags)
- ('draft ?D)
- ('flagged ?F)
- ('new ?N)
- ('passed ?P)
- ('replied ?R)
- ('seen ?S)
- ('trashed ?T)
- ('attach ?a)
- ('encrypted ?x)
- ('signed ?s)
- ('unread ?u))))
- (concat (and kar (string kar))
- (mu4e~flags-to-string-raw (cdr flags))))))
-
-(defun mu4e-flags-to-string (flags)
- "Remove duplicates and sort the output of `mu4e~flags-to-string-raw'."
- (concat
- (sort (remove-duplicates
- (append (mu4e~flags-to-string-raw flags) nil)) '>)))
-
-(defun mu4e~string-to-flags-1 (str)
- "Convert a string with message flags as seen in Maildir
-messages into a list of flags in; flags are symbols draft,
-flagged, new, passed, replied, seen, trashed and the string is
-the concatenation of the uppercased first letters of these flags,
-as per [1]. Other letters than the ones listed here are ignored.
-Also see `mu4e-flags-to-string'.
-\[1\]: http://cr.yp.to/proto/maildir.html."
- (when (/= 0 (length str))
- (let ((flag
- (case (string-to-char str)
- (?D 'draft)
- (?F 'flagged)
- (?P 'passed)
- (?R 'replied)
- (?S 'seen)
- (?T 'trashed))))
- (append (when flag (list flag))
- (mu4e~string-to-flags-1 (substring str 1))))))
-
-(defun mu4e-string-to-flags (str)
- "Convert a string with message flags as seen in Maildir messages
-into a list of flags in; flags are symbols draft, flagged, new,
-passed, replied, seen, trashed and the string is the concatenation
-of the uppercased first letters of these flags, as per [1]. Other
-letters than the ones listed here are ignored. Also see
-`mu4e-flags-to-string'. \[1\]:
-http://cr.yp.to/proto/maildir.html "
- ;; "Remove duplicates from the output of `mu4e~string-to-flags-1'"
- (remove-duplicates (mu4e~string-to-flags-1 str)))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-(defun mu4e-display-size (size)
- "Get a string representation of SIZE (in bytes)."
- (cond
- ((>= size 1000000) (format "%2.1fM" (/ size 1000000.0)))
- ((and (>= size 1000) (< size 1000000))
- (format "%2.1fK" (/ size 1000.0)))
- ((< size 1000) (format "%d" size))
- (t (propertize "?" 'face 'mu4e-system-face))))
-
-
-(defun mu4e-display-manual ()
- "Display the mu4e manual page for the current mode.
-Or go to the top level if there is none."
- (interactive)
- (info (case major-mode
- ('mu4e-main-mode "(mu4e)Main view")
- ('mu4e-headers-mode "(mu4e)Headers view")
- ('mu4e-view-mode "(mu4e)Message view")
- (t "mu4e"))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e-last-query ()
- "Get the most recent query or nil if there is none."
- (when (buffer-live-p mu4e~headers-buffer)
- (with-current-buffer mu4e~headers-buffer
- mu4e~headers-last-query)))
-
-(defun mu4e-select-other-view ()
- "When the headers view is selected, select the message view (if
-that has a live window), and vice versa."
- (interactive)
- (let* ((other-buf
- (cond
- ((eq major-mode 'mu4e-headers-mode)
- mu4e~view-buffer)
- ((eq major-mode 'mu4e-view-mode)
- mu4e~headers-buffer)))
- (other-win (and other-buf (get-buffer-window other-buf))))
- (if (window-live-p other-win)
- (select-window other-win)
- (mu4e-message "No window to switch to"))))
-
-
-(defconst mu4e-output-buffer-name "*mu4e-output*"
- "*internal* Name of the mu4e output buffer.")
-
-(defun mu4e-process-file-through-pipe (path pipecmd)
- "Process file at PATH through a pipe with PIPECMD."
- (let ((buf (get-buffer-create mu4e-output-buffer-name)))
- (with-current-buffer buf
- (let ((inhibit-read-only t))
- (erase-buffer)
- (call-process-shell-command pipecmd path t t)
- (view-mode)))
- (switch-to-buffer buf)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar mu4e~lists-hash nil
- "Hashtable of mailing-list-id => shortname, based on
- `mu4e~mailing-lists' and `mu4e-user-mailing-lists'.")
-
-(defun mu4e-get-mailing-list-shortname (list-id)
- "Get the shortname for a mailing-list with list-id LIST-ID. based
-on `mu4e~mailing-lists', `mu4e-user-mailing-lists', and
-`mu4e-mailing-list-patterns'."
- (unless mu4e~lists-hash
- (setq mu4e~lists-hash (make-hash-table :test 'equal))
- (dolist (cell mu4e~mailing-lists)
- (puthash (car cell) (cdr cell) mu4e~lists-hash))
- (dolist (cell mu4e-user-mailing-lists)
- (puthash (car cell) (cdr cell) mu4e~lists-hash)))
- (or
- (gethash list-id mu4e~lists-hash)
- (and (boundp 'mu4e-mailing-list-patterns)
- (cl-member-if
- (lambda (pattern)
- (string-match pattern list-id))
- mu4e-mailing-list-patterns)
- (match-string 1 list-id))
- ;; if it's not in the db, take the part until the first dot if there is one;
- ;; otherwise just return the whole thing
- (if (string-match "\\([^.]*\\)\\." list-id)
- (match-string 1 list-id)
- list-id)))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defvar mu4e-index-updated-hook nil
- "Hook run when the indexing process had one or more updated messages.
-This can be used as a simple way to invoke some action when new
-messages appear, but note that an update in the index does not
-necessarily mean a new message.")
-
-;; some handler functions for server messages
-;;
-(defun mu4e-info-handler (info)
- "Handler function for (:info ...) sexps received from the server
-process."
- (let ((type (plist-get info :info)))
- (cond
- ((eq type 'add) t) ;; do nothing
- ((eq type 'index)
- (if (eq (plist-get info :status) 'running)
- (mu4e-index-message "Indexing... processed %d, updated %d"
- (plist-get info :processed) (plist-get info :updated))
- (progn
- (mu4e-index-message
- "Indexing completed; processed %d, updated %d, cleaned-up %d"
- (plist-get info :processed) (plist-get info :updated)
- (plist-get info :cleaned-up))
- (unless (zerop (plist-get info :updated))
- (run-hooks 'mu4e-index-updated-hook)))))
- ((plist-get info :message)
- (mu4e-index-message "%s" (plist-get info :message))))))
-
-(defun mu4e-error-handler (errcode errmsg)
- "Handler function for showing an error."
- ;; don't use mu4e-error here; it's running in the process filter context
- (case errcode
- (4 (user-error "No matches for this search query."))
- (t (error "Error %d: %s" errcode errmsg))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-;;; RFC2822 handling of phrases in mail-addresses
-;;; The optional display-name contains a phrase, it sits before the angle-addr
-;;; as specified in RFC2822 for email-addresses in header fields.
-;;; contributed by jhelberg
-
-(defun mu4e~rfc822-phrase-type (ph)
- "Return either atom, quoted-string, a corner-case or nil. This
- checks for empty string first. Then quotes around the phrase
- (returning 'rfc822-quoted-string). Then whether there is a quote
- inside the phrase (returning 'rfc822-containing-quote).
- The reverse of the RFC atext definition is then tested.
- If it matches, nil is returned, if not, it is an 'rfc822-atom, which
- is returned."
- (cond
- ((= (length ph) 0) 'rfc822-empty)
- ((= (aref ph 0) ?\")
- (if (string-match "\"\\([^\"\\\n]\\|\\\\.\\|\\\\\n\\)*\"" ph)
- 'rfc822-quoted-string
- 'rfc822-containing-quote)) ; starts with quote, but doesn't end with one
- ((string-match-p "[\"]" ph) 'rfc822-containing-quote)
- ((string-match-p "[\000-\037()\*<>@,;:\\\.]+" ph) nil)
- (t 'rfc822-atom)))
-
-(defun mu4e~rfc822-quoteit (ph)
- "Quote RFC822 phrase only if necessary.
- Atoms and quoted strings don't need quotes. The rest do. In
- case a phrase contains a quote, it will be escaped."
- (let ((type (mu4e~rfc822-phrase-type ph)))
- (cond
- ((eq type 'rfc822-atom) ph)
- ((eq type 'rfc822-quoted-string) ph)
- ((eq type 'rfc822-containing-quote)
- (format "\"%s\""
- (replace-regexp-in-string "\"" "\\\\\"" ph)))
- (t (format "\"%s\"" ph)))))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defsubst mu4e~process-contact (contact)
- "Process CONTACT, and either return nil when it should not be included,
-or (rfc822-string . CONTACT) otherwise."
- (when mu4e-contact-rewrite-function
- (setq contact (funcall mu4e-contact-rewrite-function contact)))
- (when contact
- (let ((name (plist-get contact :name))
- (mail (plist-get contact :mail))
- (ignore-rx (or mu4e-compose-complete-ignore-address-regexp "$^")))
- (when (and mail (not (string-match ignore-rx mail)))
- (cons
- (if name (format "%s <%s>" (mu4e~rfc822-quoteit name) mail) mail)
- contact)))))
-
-
-(defun mu4e~sort-contacts (contacts)
- "Destructively sort contacts (only for cycling) in order of
- 'mostly likely contact'.t See the code for the detail"
- (let* ((now (+ (float-time) 3600)) ;; allow for clock diffs
- (recent (- (float-time) (* 15 24 3600))))
- (sort* contacts
- (lambda (c1 c2)
- (let* ( (c1 (cdr c1)) (c2 (cdr c2))
- (personal1 (plist-get c1 :personal))
- (personal2 (plist-get c2 :personal))
- ;; note: freq, tstamp can only be missing if the rewrite
- ;; function removed them. If the rewrite function changed the
- ;; contact somehow, we guess it's important.
- (freq1 (or (plist-get c1 :freq) 500))
- (freq2 (or (plist-get c2 :freq) 500))
- (tstamp1 (or (plist-get c1 :tstamp) now))
- (tstamp2 (or (plist-get c2 :tstamp) now)))
- ;; only one is personal? if so, that one comes first
- (if (not (equal personal1 personal2))
- (if personal1 t nil)
- ;; only one is recent? that one comes first
- (if (not (equal (> tstamp1 recent) (> tstamp2 recent)))
- (> tstamp1 tstamp2)
- ;; otherwise, use the frequency
- (> freq1 freq2))))))))
-
-(defun mu4e~sort-contacts-for-completion (contacts)
- "Takes CONTACTS, which is a list of RFC-822 addresses, and sort them based
-on the ranking in `mu4e~contacts.'"
- (sort* contacts
- (lambda (c1 c2)
- (let ((rank1 (gethash c1 mu4e~contacts))
- (rank2 (gethash c2 mu4e~contacts)))
- (< rank1 rank2)))))
-
-;; start and stopping
-(defun mu4e~fill-contacts (contact-data)
- "We receive a list of contacts, which each contact of the form
- (:me NAME :mail EMAIL :tstamp TIMESTAMP :freq FREQUENCY)
-and fill the hash `mu4e~contacts-for-completion' with it, with
-each contact mapped to an integer for their ranking.
-
-This is used by the completion function in mu4e-compose."
- (let ((contacts) (rank 0))
- (dolist (contact contact-data)
- (let ((contact-maybe (mu4e~process-contact contact)))
- ;; note, this gives cells (rfc822-address . contact)
- (when contact-maybe (push contact-maybe contacts))))
- (setq contacts (mu4e~sort-contacts contacts))
- ;; now, we have our nicely sorted list, map them to a list
- ;; of increasing integers. We use that map in the composer
- ;; to sort them there. It would have been so much easier if emacs
- ;; allowed us to use the sorted-list as-is, but no such luck.
- (setq mu4e~contacts (make-hash-table :test 'equal :weakness nil
- :size (length contacts)))
- (dolist (contact contacts)
- (puthash (car contact) rank mu4e~contacts)
- (incf rank))
- (mu4e-index-message "Contacts received: %d"
- (hash-table-count mu4e~contacts))))
-
-(defun mu4e~check-requirements ()
- "Check for the settings required for running mu4e."
- (unless (>= emacs-major-version 23)
- (mu4e-error "Emacs >= 23.x is required for mu4e"))
- (when mu4e~server-props
- (let ((version (plist-get mu4e~server-props :version)))
- (unless (string= version mu4e-mu-version)
- (mu4e-error "mu server has version %s, but we need %s"
- version mu4e-mu-version))))
- (unless (and mu4e-mu-binary (file-executable-p mu4e-mu-binary))
- (mu4e-error "Please set `mu4e-mu-binary' to the full path to the mu
- binary."))
- (unless mu4e-maildir
- (mu4e-error "Please set `mu4e-maildir' to the full path to your
- Maildir directory."))
- ;; expand mu4e-maildir, mu4e-attachment-dir
- (setq mu4e-maildir (expand-file-name mu4e-maildir))
- (unless (mu4e-create-maildir-maybe mu4e-maildir)
- (mu4e-error "%s is not a valid maildir directory" mu4e-maildir))
- (dolist (var '(mu4e-sent-folder mu4e-drafts-folder
- mu4e-trash-folder))
- (unless (and (boundp var) (symbol-value var))
- (mu4e-error "Please set %S" var))
- (unless (functionp (symbol-value var)) ;; functions are okay, too
- (let* ((dir (symbol-value var))
- (path (concat mu4e-maildir dir)))
- (unless (string= (substring dir 0 1) "/")
- (mu4e-error "%S must start with a '/'" dir))
- (unless (mu4e-create-maildir-maybe path)
- (mu4e-error "%s (%S) does not exist" path var))))))
-
-
-(defun mu4e-running-p ()
- "Whether mu4e is running.
-Checks whether the server process is live."
- (mu4e~proc-running-p))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; starting / getting mail / updating the index
-;;
-;;
-(defvar mu4e~update-timer nil
- "The mu4e update timer.")
-(defconst mu4e~update-name "*mu4e-update*"
- "Name of the process and buffer to update mail.")
-(defconst mu4e~update-buffer-height 8
- "Height of the mu4e message retrieval/update buffer.")
-
-(defvar mu4e~get-mail-ask-password "mu4e get-mail: Enter password: "
- "Query string for `mu4e-get-mail-command' password.")
-(defvar mu4e~get-mail-password-regexp "^Remote: Enter password: $"
- "Regexp to match a password query in the `mu4e-get-mail-command' output.")
-
-(defun mu4e~request-contacts ()
- "If `mu4e-compose-complete-addresses' is non-nil, get/update the
-list of contacts we use for autocompletion; otherwise, do nothing."
- (when mu4e-compose-complete-addresses
- (setq mu4e-contacts-func 'mu4e~fill-contacts)
- (mu4e~proc-contacts
- mu4e-compose-complete-only-personal
- (when mu4e-compose-complete-only-after
- (float-time
- (apply 'encode-time
- (mu4e-parse-time-string mu4e-compose-complete-only-after)))))))
-
-(defun mu4e~start (&optional func)
- "If `mu4e-contexts' have been defined, but we don't have a
-context yet, switch to the matching one, or none matches, the
-first.
-If mu4e is already running, execute function FUNC (if non-nil).
-Otherwise, check various requirements, then start mu4e. When
-successful, call FUNC (if non-nil) afterwards."
- ;; if we're already running, simply go to the main view
- (if (mu4e-running-p) ;; already running?
- (when func (funcall func)) ;; yes! run func if defined
- (progn
- ;; no! try to set a context, do some checks, set up pong handler and ping
- ;; the server maybe switch the context
- (mu4e~context-autoswitch nil mu4e-context-policy)
- (lexical-let ((func func))
- (mu4e~check-requirements)
- ;; set up the 'pong' handler func
- (setq mu4e-pong-func
- (lambda (props)
- (setq mu4e~server-props props) ;; save props from the server
- (let ((version (plist-get props :version))
- (doccount (plist-get props :doccount)))
- (mu4e~check-requirements)
- (when func (funcall func))
- (when (and mu4e-update-interval (null mu4e~update-timer))
- (setq mu4e~update-timer
- (run-at-time
- 0 mu4e-update-interval
- (lambda () (mu4e-update-mail-and-index
- mu4e-index-update-in-background)))))
- (mu4e-message "Started mu4e with %d message%s in store"
- doccount (if (= doccount 1) "" "s"))))))
- ;; wake up server
- (mu4e~proc-ping)
- ;; maybe request the list of contacts, automatically refresh after
- ;; reindexing
- (mu4e~request-contacts)
- (add-hook 'mu4e-index-updated-hook 'mu4e~request-contacts))))
-
-(defun mu4e-clear-caches ()
- "Clear any cached resources."
- (setq
- mu4e-maildir-list nil
- mu4e~contacts nil))
-
-(defun mu4e~stop ()
- "Stop the mu4e session."
- (when mu4e~update-timer
- (cancel-timer mu4e~update-timer)
- (setq mu4e~update-timer nil))
- (mu4e-clear-caches)
- (mu4e~proc-kill)
- ;; kill all main/view/headers buffer
- (mapcar
- (lambda (buf)
- (with-current-buffer buf
- (when (member major-mode
- '(mu4e-headers-mode mu4e-view-mode mu4e-main-mode))
- (kill-buffer))))
- (buffer-list)))
-
-
-
-(defvar mu4e~progress-reporter nil
- "Internal, the progress reporter object.")
-
-(defun mu4e~get-mail-process-filter (proc msg)
- "Filter the output of `mu4e-get-mail-command'.
-Currently the filter only checks if the command asks for a password
-by matching the output against `mu4e~get-mail-password-regexp'.
-The messages are inserted into the process buffer.
-
-Also scrolls to the final line, and update the progress throbber."
- (when mu4e~progress-reporter
- (progress-reporter-update mu4e~progress-reporter))
-
- (when (string-match mu4e~get-mail-password-regexp msg)
- (if (process-get proc 'x-interactive)
- (process-send-string proc
- (concat (read-passwd mu4e~get-mail-ask-password)
- "\n"))
- ;; TODO kill process?
- (mu4e-error "Unrecognized password request")))
- (when (process-buffer proc)
- (let ((inhibit-read-only t)
- (procwin (get-buffer-window (process-buffer proc))))
- ;; Insert at end of buffer. Leave point alone.
- (with-current-buffer (process-buffer proc)
- (goto-char (point-max))
- (if (string-match ".*\r\\(.*\\)" msg)
- (progn
- (kill-line 0)
- (insert (match-string 1 msg)))
- (insert msg)))
- ;; Auto-scroll unless user is interacting with the window.
- (when (and (window-live-p procwin)
- (not (eq (selected-window) procwin)))
- (with-selected-window procwin
- (goto-char (point-max)))))))
-
-(defun mu4e-update-index ()
- "Update the mu4e index."
- (interactive)
- (unless mu4e-maildir
- (mu4e-error "`mu4e-maildir' is not defined"))
- (mu4e~proc-index mu4e-maildir
- mu4e-user-mail-address-list
- mu4e-index-cleanup
- mu4e-index-lazy-check))
-
-(defvar mu4e~update-buffer nil
- "Internal, store the buffer of the update process when
- updating.")
-
-(define-derived-mode mu4e~update-mail-mode special-mode "mu4e:update"
- "Major mode used for retrieving new e-mail messages in `mu4e'.")
-
-(define-key mu4e~update-mail-mode-map (kbd "q") 'mu4e-interrupt-update-mail)
-
-(defun mu4e~temp-window (buf height)
- "Create a temporary window with HEIGHT at the bottom of the
-frame to display buffer BUF."
- (let ((win
- (split-window
- (frame-root-window)
- (- (window-height (frame-root-window)) height))))
- (set-window-buffer win buf)
- (set-window-dedicated-p win t)
- win))
-
-(defun mu4e~update-sentinel-func (proc msg)
- "Sentinel function for the update process."
- (when mu4e~progress-reporter
- (progress-reporter-done mu4e~progress-reporter)
- (setq mu4e~progress-reporter nil))
- (let* ((status (process-status proc))
- (code (process-exit-status proc))
- (maybe-error (or (not (eq status 'exit)) (/= code 0)))
- (buf (and (buffer-live-p mu4e~update-buffer) mu4e~update-buffer))
- (win (and buf (get-buffer-window buf))))
- (message nil)
- (if maybe-error
- (progn
- (when mu4e-index-update-error-warning
- (mu4e-message "Update process returned with non-zero exit code")
- (sit-for 5))
- (when mu4e-index-update-error-continue
- (mu4e-update-index)))
- (mu4e-update-index))
- (if (window-live-p win)
- (with-selected-window win (kill-buffer-and-window))
- (when (buffer-live-p buf) (kill-buffer buf)))))
-
-;; complicated function, as it:
-;; - needs to check for errors
-;; - (optionally) pop-up a window
-;; - (optionally) check password requests
-(defun mu4e~update-mail-and-index-real (run-in-background)
- "Get a new mail by running `mu4e-get-mail-command'. If
-RUN-IN-BACKGROUND is non-nil (or called with prefix-argument),
-run in the background; otherwise, pop up a window."
- (let* ((process-connection-type t)
- (proc (start-process-shell-command
- "mu4e-update" " *mu4e-update*"
- mu4e-get-mail-command))
- (buf (process-buffer proc))
- (win (or run-in-background
- (mu4e~temp-window buf mu4e~update-buffer-height))))
- (setq mu4e~update-buffer buf)
- (when (window-live-p win)
- (with-selected-window win
- ;; ;;(switch-to-buffer buf)
- ;; (set-window-dedicated-p win t)
- (erase-buffer)
- (insert "\n") ;; FIXME -- needed so output start
- (mu4e~update-mail-mode)))
- (setq mu4e~progress-reporter
- (unless mu4e-hide-index-messages
- (make-progress-reporter
- (mu4e-format "Retrieving mail..."))))
- (set-process-sentinel proc 'mu4e~update-sentinel-func)
- ;; if we're running in the foreground, handle password requests
- (unless run-in-background
- (process-put proc 'x-interactive (not run-in-background))
- (set-process-filter proc 'mu4e~get-mail-process-filter))))
-
-(defun mu4e-update-mail-and-index (run-in-background)
- "Get a new mail by running `mu4e-get-mail-command'. If
-run-in-background is non-nil (or called with prefix-argument), run
-in the background; otherwise, pop up a window."
- (interactive "P")
- (unless mu4e-get-mail-command
- (mu4e-error "`mu4e-get-mail-command' is not defined"))
- (if (and (buffer-live-p mu4e~update-buffer)
- (process-live-p (get-buffer-process mu4e~update-buffer)))
- (mu4e-message "Update process is already running")
- (progn
- (run-hooks 'mu4e-update-pre-hook)
- (mu4e~update-mail-and-index-real run-in-background))))
-
-(defun mu4e-interrupt-update-mail ()
- "Stop the update process by sending SIGINT to it."
- (interactive)
- (let* ((proc (and (buffer-live-p mu4e~update-buffer)
- (get-buffer-process mu4e~update-buffer))))
- (when (process-live-p proc)
- (interrupt-process proc t))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;; logging / debugging
-(defvar mu4e~log-max-lines 1200
- "*internal* Last <n> number of lines to keep around in the buffer.")
-(defconst mu4e~log-buffer-name "*mu4e-log*"
- "*internal* Name of the logging buffer.")
-
-(defun mu4e-log (type frm &rest args)
- "Write a message of TYPE with format-string FRM and ARGS in
-*mu4e-log* buffer, if the variable mu4e-debug is non-nil. Type is
-either 'to-server, 'from-server or 'misc. This function is meant for debugging."
- (when mu4e-debug
- (with-current-buffer (get-buffer-create mu4e~log-buffer-name)
- (view-mode)
- (setq buffer-undo-list t)
- (let* ((inhibit-read-only t)
- (tstamp (propertize (format-time-string "%Y-%m-%d %T"
- (current-time))
- 'face 'font-lock-string-face))
- (msg-face
- (case type
- (from-server 'font-lock-type-face)
- (to-server 'font-lock-function-name-face)
- (misc 'font-lock-variable-name-face)
- (error 'font-lock-warning-face)
- (otherwise (mu4e-error "Unsupported log type"))))
- (msg (propertize (apply 'format frm args) 'face msg-face)))
- (goto-char (point-max))
- (insert tstamp
- (case type
- (from-server " <- ")
- (to-server " -> ")
- (error " !! ")
- (otherwise " "))
- msg "\n")
-
- ;; if `mu4e-log-max-lines is specified and exceeded, clearest the oldest
- ;; lines
- (when (numberp mu4e~log-max-lines)
- (let ((lines (count-lines (point-min) (point-max))))
- (when (> lines mu4e~log-max-lines)
- (goto-char (point-max))
- (forward-line (- mu4e~log-max-lines lines))
- (beginning-of-line)
- (delete-region (point-min) (point)))))))))
-
-(defun mu4e-toggle-logging ()
- "Toggle between enabling/disabling debug-mode (in debug-mode,
-mu4e logs some of its internal workings to a log-buffer. See
-`mu4e-visit-log'."
- (interactive)
- (mu4e-log 'misc "logging disabled")
- (setq mu4e-debug (not mu4e-debug))
- (mu4e-message "debug logging has been %s"
- (if mu4e-debug "enabled" "disabled"))
- (mu4e-log 'misc "logging enabled"))
-
-(defun mu4e-show-log ()
- "Visit the mu4e debug log."
- (interactive)
- (let ((buf (get-buffer mu4e~log-buffer-name)))
- (unless (buffer-live-p buf)
- (mu4e-warn "No debug log available"))
- (switch-to-buffer buf)))
-
-
-(defun mu4e-split-ranges-to-numbers (str n)
- "Convert STR containing attachment numbers into a list of numbers.
-STR is a string; N is the highest possible number in the list.
-This includes expanding e.g. 3-5 into 3,4,5. If the letter
-\"a\" ('all')) is given, that is expanded to a list with numbers [1..n]."
- (let ((str-split (split-string str))
- beg end list)
- (dolist (elem str-split list)
- ;; special number "a" converts into all attachments 1-N.
- (when (equal elem "a")
- (setq elem (concat "1-" (int-to-string n))))
- (if (string-match "\\([0-9]+\\)-\\([0-9]+\\)" elem)
- ;; we have found a range A-B, which needs converting
- ;; into the numbers A, A+1, A+2, ... B.
- (progn
- (setq beg (string-to-number (match-string 1 elem))
- end (string-to-number (match-string 2 elem)))
- (while (<= beg end)
- (add-to-list 'list beg 'append)
- (setq beg (1+ beg))))
- ;; else just a number
- (add-to-list 'list (string-to-number elem) 'append)))
- ;; Check that all numbers are valid.
- (mapc
- #'(lambda (x)
- (cond
- ((> x n)
- (mu4e-warn "Attachment %d bigger than maximum (%d)" x n))
- ((< x 1)
- (mu4e-warn "Attachment number must be greater than 0 (%d)" x))))
- list)))
-
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defvar mu4e-imagemagick-identify "identify"
- "Name/path of the Imagemagick 'identify' program.")
-
-(defun mu4e-display-image (imgpath &optional maxwidth maxheight)
- "Display image IMG at point; optionally specify MAXWIDTH and
-MAXHEIGHT. Function tries to use imagemagick if available (ie.,
-emacs was compiled with inmagemagick support); otherwise MAXWIDTH
-and MAXHEIGHT are ignored."
- (let* ((have-im (and (fboundp 'imagemagick-types)
- (imagemagick-types))) ;; hmm, should check for specific type
- (identify (and have-im maxwidth
- (executable-find mu4e-imagemagick-identify)))
- (props (and identify (shell-command-to-string
- (format "%s -format '%%w' %s"
- identify (shell-quote-argument imgpath)))))
- (width (and props (string-to-number props)))
- (img (if have-im
- (if (> (or width 0) (or maxwidth 0))
- (create-image imgpath 'imagemagick nil :width maxwidth)
- (create-image imgpath 'imagemagick))
- (create-image imgpath))))
- (when img
- (save-excursion
- (insert "\n")
- (let ((size (image-size img))) ;; inspired by gnus..
- (insert-char ?\n
- (max 0 (round (- (window-height) (or maxheight (cdr size)) 1) 2)))
- (insert-char ?\.
- (max 0 (round (- (window-width) (or maxwidth (car size))) 2)))
- (insert-image img))))))
-
-
-(defun mu4e-hide-other-mu4e-buffers ()
- "Bury mu4e-buffers (main, headers, view) (and delete all windows
-displaying it). Do _not_ bury the current buffer, though."
- (interactive)
- (let ((curbuf (current-buffer)))
- ;; note: 'walk-windows' does not seem to work correctly when modifying
- ;; windows; therefore, the doloops here
- (dolist (frame (frame-list))
- (dolist (win (window-list frame nil))
- (with-current-buffer (window-buffer win)
- (unless (eq curbuf (current-buffer))
- (when (member major-mode '(mu4e-headers-mode mu4e-view-mode))
- (when (eq t (window-deletable-p win))
- (delete-window win))))))) t))
-
-
-(defun mu4e-get-time-date (prompt)
- "Determine the emacs time value for the time/date entered by user
- after PROMPT. Formats are all that are accepted by
- `parse-time-string'."
- (let ((timestr (read-string (mu4e-format "%s" prompt))))
- (apply 'encode-time (mu4e-parse-time-string timestr))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(define-derived-mode mu4e-org-mode org-mode "mu4e:org"
- "Major mode for mu4e documents, derived from
- `org-mode'.")
-
-(defun mu4e-info (path)
- "Show a buffer with the information (an org-file) at PATH."
- (interactive)
- (unless (file-exists-p path)
- (mu4e-error "Cannot find %s" path))
- (lexical-let ((curbuf (current-buffer)))
- (find-file path)
- (mu4e-org-mode)
- (setq buffer-read-only t)
- (define-key mu4e-org-mode-map (kbd "q")
- (lambda ()
- (interactive)
- (bury-buffer)
- (switch-to-buffer curbuf)))))
-
-(defun mu4e-about ()
- "Show the mu4e 'about' page."
- (interactive)
- (mu4e-info (concat mu4e-doc-dir "/mu4e-about.org")))
-
-(defun mu4e-news ()
- "Show the mu4e 'about' page."
- (interactive)
- (mu4e-info (concat mu4e-doc-dir "/NEWS.org")))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun mu4e-refresh-message (path maildir)
- "Re-parse message at PATH and MAILDIR; if this works, we will
-receive (:info add :path <path> :docid <docid>) as well as (:update
-<msg-sexp>)."
- (mu4e~proc-add path maildir))
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defun mu4e~fontify-cited ()
- "Colorize message content based on the citation level. This is
-used in the view and compose modes."
- (save-excursion
- (goto-char (point-min))
- (when (search-forward-regexp "^\n" nil t) ;; search the first empty line
- (while (re-search-forward mu4e-cited-regexp nil t)
- (let* ((level (string-width (replace-regexp-in-string
- "[^>]" "" (match-string 0))))
- (face (unless (zerop level)
- (intern-soft (format "mu4e-cited-%d-face" level)))))
- (when face
- (add-text-properties (line-beginning-position 1)
- (line-end-position 1) `(face ,face))))))))
-
-(defun mu4e~fontify-signature ()
- "Give the message signatures a distinctive color. This is used in
-the view and compose modes."
- (let ((inhibit-read-only t))
- (save-excursion
- ;; give the footer a different color...
- (goto-char (point-min))
- (let ((p (search-forward "^-- *$" nil t)))
- (when p
- (add-text-properties p (point-max) '(face mu4e-footer-face)))))))
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(defun mu4e~quote-for-modeline (str)
- "Quote a string to be used literally in the modeline."
- (replace-regexp-in-string "%" "%%" str t t))
-
-
-(provide 'mu4e-utils)
-;;; End of mu4e-utils.el