* rename many internal functions to have a mu4e~ prefix (WIP)

- this allows to distinguish between internal and external stuff
  - the ~ is behind the 'z' in ascii, so last in the completion buffer
This commit is contained in:
djcb
2012-04-23 20:35:14 +03:00
parent 2f2853c0dd
commit 927e26ec05
8 changed files with 473 additions and 484 deletions

View File

@ -38,7 +38,7 @@
(require 'mu4e-view) (require 'mu4e-view)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e--cite-original (msg) (defun mu4e~compose-cite-original (msg)
"Return a cited version of the original message MSG (ie., the "Return a cited version of the original message MSG (ie., the
plist). This function use gnus' `message-cite-function', and as plist). This function use gnus' `message-cite-function', and as
such all its settings apply." such all its settings apply."
@ -51,13 +51,13 @@ such all its settings apply."
(buffer-string))) (buffer-string)))
(defun mu4e--header (hdr val) (defun mu4e~compose-header (hdr val)
"Return a header line of the form HDR: VAL\n. If VAL is nil, "Return a header line of the form HDR: VAL\n. If VAL is nil,
return nil." return nil."
(when val (format "%s: %s\n" hdr val))) (when val (format "%s: %s\n" hdr val)))
(defun mu4e--refererences-construct (msg) (defun mu4e~compose-refererences-construct (msg)
"Construct the value of the References: header based on MSG as a "Construct the value of the References: header based on MSG as a
comma-separated string. Normally, this the concatenation of the comma-separated string. Normally, this the concatenation of the
existing References (which may be empty) and the message-id. If the existing References (which may be empty) and the message-id. If the
@ -76,7 +76,7 @@ return nil."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; determine the recipient fields for new messages ;; determine the recipient fields for new messages
(defun mu4e--recipients-list-to-string (lst) (defun mu4e~compose-recipients-list-to-string (lst)
"Convert a lst LST of address cells into a string with a list of "Convert a lst LST of address cells into a string with a list of
e-mail addresses. If LST is nil, returns nil." e-mail addresses. If LST is nil, returns nil."
(when lst (when lst
@ -89,7 +89,7 @@ e-mail addresses. If LST is nil, returns nil."
(format "%s" email)))) (format "%s" email))))
lst ", "))) lst ", ")))
(defun mu4e--address-cell-equal (cell1 cell2) (defun mu4e~compose-address-cell-equal (cell1 cell2)
"Return t if cell1 and cell2 have the same e-mail "Return t if cell1 and cell2 have the same e-mail
address (case-insensitively), nil otherwise. cell1 and cell2 are address (case-insensitively), nil otherwise. cell1 and cell2 are
cons cells (NAME . EMAIL)." cons cells (NAME . EMAIL)."
@ -99,7 +99,7 @@ e-mail addresses. If LST is nil, returns nil."
(defun mu4e--create-to-lst (origmsg) (defun mu4e~compose-create-to-lst (origmsg)
"Create a list of address for the To: in a new message, based on "Create a list of address for the To: in a new message, based on
the original message ORIGMSG. If the Reply-To address is set, use the original message ORIGMSG. If the Reply-To address is set, use
that, otherwise use the From address. Note, whatever was in the To: that, otherwise use the From address. Note, whatever was in the To:
@ -109,10 +109,10 @@ field before, goes to the Cc:-list (if we're doing a reply-to-all)."
(or reply-to (or reply-to
(delete-duplicates (delete-duplicates
(plist-get origmsg :from) (plist-get origmsg :from)
:test #'mu4e--address-cell-equal)))) :test #'mu4e~compose-address-cell-equal))))
to-lst)) to-lst))
(defun mu4e--create-cc-lst (origmsg reply-all) (defun mu4e~compose-create-cc-lst (origmsg reply-all)
"Create a list of address for the Cc: in a new message, based on "Create a list of address for the Cc: in a new message, based on
the original message ORIGMSG, and whether it's a reply-all." the original message ORIGMSG, and whether it's a reply-all."
(when reply-all (when reply-all
@ -121,7 +121,7 @@ the original message ORIGMSG, and whether it's a reply-all."
(append (append
(plist-get origmsg :to) (plist-get origmsg :to)
(plist-get origmsg :cc)) (plist-get origmsg :cc))
:test #'mu4e--address-cell-equal)) :test #'mu4e~compose-address-cell-equal))
;; now we have the basic list, but we must remove ;; now we have the basic list, but we must remove
;; addresses also in the to list ;; addresses also in the to list
(cc-lst (cc-lst
@ -129,8 +129,8 @@ the original message ORIGMSG, and whether it's a reply-all."
(lambda (cc-cell) (lambda (cc-cell)
(find-if (find-if
(lambda (to-cell) (lambda (to-cell)
(mu4e--address-cell-equal cc-cell to-cell)) (mu4e~compose-address-cell-equal cc-cell to-cell))
(mu4e--create-to-lst origmsg))) (mu4e~compose-create-to-lst origmsg)))
cc-lst)) cc-lst))
;; finally, we need to remove ourselves from the cc-list ;; finally, we need to remove ourselves from the cc-list
(cc-lst (cc-lst
@ -138,27 +138,27 @@ the original message ORIGMSG, and whether it's a reply-all."
cc-lst cc-lst
(delete-if (delete-if
(lambda (cc-cell) (lambda (cc-cell)
(mu4e--address-cell-equal cc-cell (mu4e~compose-address-cell-equal cc-cell
(cons nil user-mail-address))) (cons nil user-mail-address)))
cc-lst)))) cc-lst))))
cc-lst))) cc-lst)))
(defun mu4e--recipients-construct (field origmsg &optional reply-all) (defun mu4e~compose-recipients-construct (field origmsg &optional reply-all)
"Create value (a string) for the recipient field FIELD (a "Create value (a string) for the recipient field FIELD (a
symbol, :to or :cc), based on the original message ORIGMSG, symbol, :to or :cc), based on the original message ORIGMSG,
and (optionally) REPLY-ALL which indicates this is a reply-to-all and (optionally) REPLY-ALL which indicates this is a reply-to-all
message. Return nil if there are no recipients for the particular field." message. Return nil if there are no recipients for the particular field."
(mu4e--recipients-list-to-string (mu4e~compose-recipients-list-to-string
(case field (case field
(:to (:to
(mu4e--create-to-lst origmsg)) (mu4e~compose-create-to-lst origmsg))
(:cc (:cc
(mu4e--create-cc-lst origmsg reply-all)) (mu4e~compose-create-cc-lst origmsg reply-all))
(otherwise (otherwise
(error "Unsupported field"))))) (error "Unsupported field")))))
(defun mu4e--from-construct () (defun mu4e~compose-from-construct ()
"Construct a value for the From:-field of the reply to MSG, "Construct a value for the From:-field of the reply to MSG,
based on `user-full-name' and `user-mail-address'; if the latter is based on `user-full-name' and `user-mail-address'; if the latter is
nil, function returns nil." nil, function returns nil."
@ -169,10 +169,10 @@ nil, function returns nil."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e--insert-mail-header-separator () (defun mu4e~compose-insert-mail-header-separator ()
"Insert `mail-header-separator' in the first empty line of the "Insert `mail-header-separator' in the first empty line of the
message. message-mode needs this line to know where the headers end message. message-mode needs this line to know where the headers end
and the body starts. Note, in `mu4e-edit-mode, we use and the body starts. Note, in `mu4e-compose-mode, we use
`before-save-hook' and `after-save-hook' to ensure that this `before-save-hook' and `after-save-hook' to ensure that this
separator is never written to file. Also see separator is never written to file. Also see
`mu4e-remove-mail-header-separator'." `mu4e-remove-mail-header-separator'."
@ -187,22 +187,22 @@ separator is never written to file. Also see
(goto-char (point-max)) (goto-char (point-max))
(insert (concat "\n" mail-header-separator "\n")))))) (insert (concat "\n" mail-header-separator "\n"))))))
(defun mu4e--remove-mail-header-separator () (defun mu4e~compose-remove-mail-header-separator ()
"Remove `mail-header-separator; we do this before saving a "Remove `mail-header-separator; we do this before saving a
file (and restore it afterwardds), to ensure that the separator file (and restore it afterwardds), to ensure that the separator
never hits the disk. Also see `mu4e--insert-mail-header-separator." never hits the disk. Also see `mu4e~compose-insert-mail-header-separator."
(save-excursion (save-excursion
(goto-char (point-min)) (goto-char (point-min))
;; remove the --text follows this line-- separator ;; remove the --text follows this line-- separator
(when (search-forward-regexp (concat "^" mail-header-separator)) (when (search-forward-regexp (concat "^" mail-header-separator))
(replace-match "")))) (replace-match ""))))
(defun mu4e--user-wants-reply-all (origmsg) (defun mu4e~compose-user-wants-reply-all (origmsg)
"Ask user whether she wants to reply to *all* recipients if there "Ask user whether she wants to reply to *all* recipients if there
are more than 1 (based on ORIGMSG)." are more than 1 (based on ORIGMSG)."
(let* ((recipnum (let* ((recipnum
(+ (length (mu4e--create-to-lst origmsg)) (+ (length (mu4e~compose-create-to-lst origmsg))
(length (mu4e--create-cc-lst origmsg t)))) (length (mu4e~compose-create-cc-lst origmsg t))))
(response (response
(if (= recipnum 1) (if (= recipnum 1)
?a ;; with one recipient, we can reply to 'all'.... ?a ;; with one recipient, we can reply to 'all'....
@ -213,68 +213,68 @@ are more than 1 (based on ORIGMSG)."
(= response ?a))) (= response ?a)))
(defun mu4e--reply-construct (origmsg) (defun mu4e~compose-reply-construct (origmsg)
"Create a draft message as a reply to original message ORIGMSG." "Create a draft message as a reply to original message ORIGMSG."
(let* ((recipnum (let* ((recipnum
(+ (length (mu4e--create-to-lst origmsg)) (+ (length (mu4e~compose-create-to-lst origmsg))
(length (mu4e--create-cc-lst origmsg t)))) (length (mu4e~compose-create-cc-lst origmsg t))))
(reply-all (mu4e--user-wants-reply-all origmsg)) (reply-all (mu4e~compose-user-wants-reply-all origmsg))
(old-msgid (plist-get origmsg :message-id)) (old-msgid (plist-get origmsg :message-id))
(subject (or (plist-get origmsg :subject) ""))) (subject (or (plist-get origmsg :subject) "")))
(concat (concat
(mu4e--header "From" (or (mu4e--from-construct) "")) (mu4e~compose-header "From" (or (mu4e~compose-from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" (mu4e--recipients-construct :to origmsg)) (mu4e~compose-header "To" (mu4e~compose-recipients-construct :to origmsg))
(mu4e--header "Cc" (mu4e--recipients-construct :cc origmsg (mu4e~compose-header "Cc" (mu4e~compose-recipients-construct :cc origmsg
reply-all)) reply-all))
(mu4e--header "User-agent" (mu4e-user-agent)) (mu4e~compose-header "User-agent" (mu4e-user-agent))
(mu4e--header "References" (mu4e--refererences-construct origmsg)) (mu4e~compose-header "References" (mu4e~compose-refererences-construct origmsg))
(when old-msgid (when old-msgid
(mu4e--header "In-reply-to" (format "<%s>" old-msgid))) (mu4e~compose-header "In-reply-to" (format "<%s>" old-msgid)))
(mu4e--header "Subject" (mu4e~compose-header "Subject"
(concat (concat
;; if there's no Re: yet, prepend it ;; if there's no Re: yet, prepend it
(if (string-match "^Re:" subject) "" "Re:") (if (string-match "^Re:" subject) "" "Re:")
subject)) subject))
"\n\n" "\n\n"
(mu4e--cite-original origmsg)))) (mu4e~compose-cite-original origmsg))))
(defun mu4e--forward-construct (origmsg) (defun mu4e~compose-forward-construct (origmsg)
"Create a draft forward message for original message ORIGMSG." "Create a draft forward message for original message ORIGMSG."
(let ((subject (let ((subject
(or (plist-get origmsg :subject) ""))) (or (plist-get origmsg :subject) "")))
(concat (concat
(mu4e--header "From" (or (mu4e--from-construct) "")) (mu4e~compose-header "From" (or (mu4e~compose-from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" "") (mu4e~compose-header "To" "")
(mu4e--header "User-agent" (mu4e-user-agent)) (mu4e~compose-header "User-agent" (mu4e-user-agent))
(mu4e--header "References" (mu4e--refererences-construct origmsg)) (mu4e~compose-header "References" (mu4e~compose-refererences-construct origmsg))
(mu4e--header "Subject" (mu4e~compose-header "Subject"
(concat (concat
;; if there's no Fwd: yet, prepend it ;; if there's no Fwd: yet, prepend it
(if (string-match "^Fwd:" subject) "" "Fwd:") (if (string-match "^Fwd:" subject) "" "Fwd:")
subject)) subject))
"\n\n" "\n\n"
(mu4e--cite-original origmsg)))) (mu4e~compose-cite-original origmsg))))
(defun mu4e--newmsg-construct () (defun mu4e~compose-newmsg-construct ()
"Create a new message." "Create a new message."
(concat (concat
(mu4e--header "From" (or (mu4e--from-construct) "")) (mu4e~compose-header "From" (or (mu4e~compose-from-construct) ""))
(mu4e--header "Reply-To" mu4e-reply-to-address) (mu4e~compose-header "Reply-To" mu4e-reply-to-address)
(mu4e--header "To" "") (mu4e~compose-header "To" "")
(mu4e--header "User-agent" (mu4e-user-agent)) (mu4e~compose-header "User-agent" (mu4e-user-agent))
(mu4e--header "Subject" "") (mu4e~compose-header "Subject" "")
"\n")) "\n"))
(defun mu4e--open-new-draft-file (compose-type &optional msg) (defun mu4e~compose-open-new-draft-file (compose-type &optional msg)
"Open a draft file for a new message, creating it if it does not "Open a draft file for a new message, creating it if it does not
already exist, and optionally fill it with STR. Function also adds already exist, and optionally fill it with STR. Function also adds
the new message to the database. When the draft message is added to the new message to the database. When the draft message is added to
@ -293,9 +293,9 @@ use the new docid. Returns the full path to the new message."
(format-time-string "%Y%m%d" (current-time)) (format-time-string "%Y%m%d" (current-time))
(emacs-pid) (random t) hostname))) (emacs-pid) (random t) hostname)))
(str (case compose-type (str (case compose-type
(reply (mu4e--reply-construct msg)) (reply (mu4e~compose-reply-construct msg))
(forward (mu4e--forward-construct msg)) (forward (mu4e~compose-forward-construct msg))
(new (mu4e--newmsg-construct)) (new (mu4e~compose-newmsg-construct))
(t (error "unsupported compose-type %S" compose-type))))) (t (error "unsupported compose-type %S" compose-type)))))
(when str (when str
(with-current-buffer (find-file-noselect draft) (with-current-buffer (find-file-noselect draft)
@ -303,13 +303,13 @@ use the new docid. Returns the full path to the new message."
draft)) ;; return the draft buffer file draft)) ;; return the draft buffer file
(define-derived-mode mu4e-edit-mode message-mode "mu4e:edit" (define-derived-mode mu4e-compose-mode message-mode "mu4e:compose"
"Major mode for the mu4e message composition, derived from `message-mode'. "Major mode for the mu4e message composition, derived from `message-mode'.
\\{message-mode-map}." \\{message-mode-map}."
(let ((message-hidden-headers (let ((message-hidden-headers
`("^References:" "^Face:" "^X-Face:" "^X-Draft-From:" `("^References:" "^Face:" "^X-Face:" "^X-Draft-From:"
"^User-agent:"))) "^User-agent:")))
(use-local-map mu4e-edit-mode-map) (use-local-map mu4e-compose-mode-map)
(message-hide-headers) (message-hide-headers)
(make-local-variable 'before-save-hook) (make-local-variable 'before-save-hook)
(make-local-variable 'after-save-hook) (make-local-variable 'after-save-hook)
@ -325,23 +325,23 @@ use the new docid. Returns the full path to the new message."
;; hack-hack-hack... just before saving, we remove the ;; hack-hack-hack... just before saving, we remove the
;; mail-header-separator; just after saving we restore it; thus, the ;; mail-header-separator; just after saving we restore it; thus, the
;; separator should never appear on disk ;; separator should never appear on disk
(add-hook 'before-save-hook 'mu4e--remove-mail-header-separator) (add-hook 'before-save-hook 'mu4e~compose-remove-mail-header-separator)
(add-hook 'after-save-hook (add-hook 'after-save-hook
(lambda () (lambda ()
(mu4e--set-friendly-buffer-name) (mu4e~compose-set-friendly-buffer-name)
(mu4e--insert-mail-header-separator) (mu4e~compose-insert-mail-header-separator)
(set-buffer-modified-p nil))) (set-buffer-modified-p nil)))
;; update the db when the file is saved...] ;; update the db when the file is saved...]
(add-hook 'after-save-hook (add-hook 'after-save-hook
(lambda() (lambda()
(mu4e-proc-add (buffer-file-name) mu4e-drafts-folder)))) (mu4e~proc-add (buffer-file-name) mu4e-drafts-folder))))
;; notify the backend that a message has been sent. The backend will respond ;; notify the backend that a message has been sent. The backend will respond
;; with (:sent ...) sexp, which is handled in `mu4e-compose-handler'. ;; with (:sent ...) sexp, which is handled in `mu4e-compose-handler'.
(add-hook 'message-sent-hook (add-hook 'message-sent-hook
(lambda () (lambda ()
(set-buffer-modified-p t) (set-buffer-modified-p t)
(basic-save-buffer) (basic-save-buffer)
(mu4e-proc-sent (buffer-file-name) mu4e-drafts-folder))) (mu4e~proc-sent (buffer-file-name) mu4e-drafts-folder)))
;; register the function; this function will be called when the '(:sent...)' ;; register the function; this function will be called when the '(:sent...)'
;; message is received (see mu4e-proc.el) with parameters docid and path ;; message is received (see mu4e-proc.el) with parameters docid and path
(setq mu4e-sent-func 'mu4e-sent-handler) (setq mu4e-sent-func 'mu4e-sent-handler)
@ -351,10 +351,10 @@ use the new docid. Returns the full path to the new message."
(setq default-directory (expand-file-name "~/"))) (setq default-directory (expand-file-name "~/")))
(defconst mu4e--buffer-max-name-length 30 (defconst mu4e~compose-buffer-max-name-length 30
"Maximum length of the mu4e-send-buffer-name.") "Maximum length of the mu4e-send-buffer-name.")
(defun mu4e--set-friendly-buffer-name (&optional compose-type) (defun mu4e~compose-set-friendly-buffer-name (&optional compose-type)
"Set some user-friendly buffer name based on the compose type." "Set some user-friendly buffer name based on the compose type."
(let* ((subj (message-field-value "subject")) (let* ((subj (message-field-value "subject"))
(subj (unless (and subj (string-match "^[:blank:]*$" subj)) subj)) (subj (unless (and subj (string-match "^[:blank:]*$" subj)) subj))
@ -365,7 +365,7 @@ use the new docid. Returns the full path to the new message."
(otherwise "*draft*"))))) (otherwise "*draft*")))))
(rename-buffer (generate-new-buffer-name (rename-buffer (generate-new-buffer-name
(truncate-string-to-width str (truncate-string-to-width str
mu4e--buffer-max-name-length mu4e~compose-buffer-max-name-length
nil nil t))))) nil nil t)))))
@ -395,22 +395,22 @@ The name of the draft folder is constructed from the concatenation
The message file name is a unique name determined by The message file name is a unique name determined by
`mu4e-send-draft-file-name'. `mu4e-send-draft-file-name'.
The initial STR would be created from either `mu4e--reply-construct', The initial STR would be created from either `mu4e~compose-reply-construct',
ar`mu4e--forward-construct' or `mu4e--newmsg-construct'. The editing buffer is ar`mu4e~compose-forward-construct' or `mu4e~compose-newmsg-construct'. The editing buffer is
using Gnus' `message-mode'." using Gnus' `message-mode'."
(unless mu4e-maildir (error "mu4e-maildir not set")) (unless mu4e-maildir (error "mu4e-maildir not set"))
(unless mu4e-drafts-folder (error "mu4e-drafts-folder not set")) (unless mu4e-drafts-folder (error "mu4e-drafts-folder not set"))
(let ((draft (let ((draft
(if (member compose-type '(reply forward new)) (if (member compose-type '(reply forward new))
(mu4e--open-new-draft-file compose-type original-msg) (mu4e~compose-open-new-draft-file compose-type original-msg)
(if (eq compose-type 'edit) (if (eq compose-type 'edit)
(plist-get original-msg :path) (plist-get original-msg :path)
(error "unsupported compose-type %S" compose-type))))) (error "unsupported compose-type %S" compose-type)))))
(find-file draft) (find-file draft)
(mu4e-edit-mode) (mu4e-compose-mode)
;; insert mail-header-separator, which is needed by message mode to separate ;; insert mail-header-separator, which is needed by message mode to separate
;; headers and body. will be removed before saving to disk ;; headers and body. will be removed before saving to disk
(mu4e--insert-mail-header-separator) (mu4e~compose-insert-mail-header-separator)
;; include files -- e.g. when forwarding a message with attachments, ;; include files -- e.g. when forwarding a message with attachments,
;; we take those from the original. ;; we take those from the original.
(save-excursion (save-excursion
@ -428,7 +428,7 @@ using Gnus' `message-mode'."
(if (member compose-type '(new forward)) (if (member compose-type '(new forward))
(message-goto-to) (message-goto-to)
(message-goto-body)) (message-goto-body))
(mu4e--set-friendly-buffer-name compose-type) (mu4e~compose-set-friendly-buffer-name compose-type)
;; buffer is not user-modified yet ;; buffer is not user-modified yet
(set-buffer-modified-p nil))) (set-buffer-modified-p nil)))
@ -452,13 +452,13 @@ message."
(with-current-buffer(find-file-noselect path) (with-current-buffer(find-file-noselect path)
;; for Forward ('Passed') and Replied messages, try to set the appropriate ;; for Forward ('Passed') and Replied messages, try to set the appropriate
;; flag at the message forwarded or replied-to ;; flag at the message forwarded or replied-to
(mu4e--set-parent-flag docid path) (mu4e~compose-set-parent-flag docid path)
;; handle the draft -- should it be moved to the sent-folder, or elsewhere? ;; handle the draft -- should it be moved to the sent-folder, or elsewhere?
(mu4e--save-copy-maybe docid path) (mu4e~compose-save-copy-maybe docid path)
;; now, get rid of the buffer ;; now, get rid of the buffer
(kill-buffer))) (kill-buffer)))
(defun mu4e--save-copy-maybe (docid path) (defun mu4e~compose-save-copy-maybe (docid path)
"Handler function, called with DOCID and PATH for the just-sent "Handler function, called with DOCID and PATH for the just-sent
message, which will move it to the sent-folder or elsewhere, message, which will move it to the sent-folder or elsewhere,
depending on the value of `mu4e-sent-messages-behavior'. depending on the value of `mu4e-sent-messages-behavior'.
@ -467,16 +467,16 @@ Function assumes that it's executed in the context of the message
buffer." buffer."
;; first, what to do with the draft message in PATH? ;; first, what to do with the draft message in PATH?
(if (eq mu4e-sent-messages-behavior 'delete) (if (eq mu4e-sent-messages-behavior 'delete)
(mu4e-proc-remove docid) ;; remove it (mu4e~proc-remove docid) ;; remove it
;; otherwise, ;; otherwise,
(progn ;; prepare the message for saving (progn ;; prepare the message for saving
(basic-save-buffer) (basic-save-buffer)
;; now either move it to trash or to sent ;; now either move it to trash or to sent
(if (eq mu4e-sent-messages-behavior 'trash) (if (eq mu4e-sent-messages-behavior 'trash)
(mu4e-proc-move docid mu4e-trash-folder "+T-D+S") (mu4e~proc-move docid mu4e-trash-folder "+T-D+S")
(mu4e-proc-move docid mu4e-sent-folder "-T-D+S"))))) (mu4e~proc-move docid mu4e-sent-folder "-T-D+S")))))
(defun mu4e--set-parent-flag (docid path) (defun mu4e~compose-set-parent-flag (docid path)
"Set the 'replied' \"R\" flag on messages we replied to, and the "Set the 'replied' \"R\" flag on messages we replied to, and the
'passed' \"F\" flag on message we have forwarded. 'passed' \"F\" flag on message we have forwarded.
@ -509,9 +509,9 @@ buffer.
(setq forwarded-from (first refs)))))) (setq forwarded-from (first refs))))))
;; remove the <> ;; remove the <>
(when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to)) (when (and in-reply-to (string-match "<\\(.*\\)>" in-reply-to))
(mu4e-proc-move (match-string 1 in-reply-to) nil "+R")) (mu4e~proc-move (match-string 1 in-reply-to) nil "+R"))
(when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from)) (when (and forwarded-from (string-match "<\\(.*\\)>" forwarded-from))
(mu4e-proc-move (match-string 1 forwarded-from) nil "+P")))) (mu4e~proc-move (match-string 1 forwarded-from) nil "+P"))))
@ -519,7 +519,7 @@ buffer.
;; mu4e-compose-func and mu4e-send-func are wrappers so we can set ourselves ;; mu4e-compose-func and mu4e-send-func are wrappers so we can set ourselves
;; as default emacs mailer (define-mail-user-agent etc.) ;; as default emacs mailer (define-mail-user-agent etc.)
(defun mu4e--compose-func (&optional to subject other-headers continue (defun mu4e~compose-compose-func (&optional to subject other-headers continue
switch-function yank-action send-actions return-action) switch-function yank-action send-actions return-action)
"mu4e's implementation of `compose-mail'." "mu4e's implementation of `compose-mail'."

View File

@ -35,16 +35,16 @@
(require 'mu4e-mark) (require 'mu4e-mark)
;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defconst mu4e-hdrs-fringe " " "*internal* The space on the left of (defconst mu4e~hdrs-fringe " " "*internal* The space on the left of
message headers to put marks.") message headers to put marks.")
(defun mu4e-hdrs-clear () (defun mu4e~hdrs-clear ()
"Clear the header buffer and related data structures." "Clear the header buffer and related data structures."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(erase-buffer) (erase-buffer)
(mu4e--mark-clear))))) (mu4e~mark-clear)))))
(defun mu4e-hdrs-search (expr &optional full-search) (defun mu4e-hdrs-search (expr &optional full-search)
@ -52,17 +52,17 @@ message headers to put marks.")
buffer for the results. If FULL-SEARCH is non-nil return all buffer for the results. If FULL-SEARCH is non-nil return all
results, otherwise, limit number of results to results, otherwise, limit number of results to
`mu4e-search-results-limit'." `mu4e-search-results-limit'."
(let ((buf (get-buffer-create mu4e-hdrs-buffer-name)) (let ((buf (get-buffer-create mu4e~hdrs-buffer-name))
(inhibit-read-only t)) (inhibit-read-only t))
(with-current-buffer buf (with-current-buffer buf
(mu4e-hdrs-mode) (mu4e-hdrs-mode)
(setq (setq
global-mode-string (propertize expr 'face 'mu4e-title-face) global-mode-string (propertize expr 'face 'mu4e-title-face)
mu4e-last-expr expr mu4e-last-expr expr
mu4e-hdrs-buffer buf mu4e~hdrs-buffer buf
mode-name "mu4e-headers")) mode-name "mu4e-headers"))
(switch-to-buffer buf) (switch-to-buffer buf)
(mu4e-proc-find (mu4e~proc-find
(replace-regexp-in-string "\"" "\\\\\"" expr) ;; escape "\" (replace-regexp-in-string "\"" "\\\\\"" expr) ;; escape "\"
(unless full-search mu4e-search-results-limit)) (unless full-search mu4e-search-results-limit))
;;; when we're starting a new search, we also kill the ;;; when we're starting a new search, we also kill the
@ -72,22 +72,22 @@ results, otherwise, limit number of results to
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; handler functions ;; handler functions
;; ;;
;; next are a bunch of handler functions; those will be called from mu4e-proc in ;; next are a bunch of handler functions; those will be called from mu4e~proc in
;; response to output from the server process ;; response to output from the server process
(defun mu4e-hdrs-view-handler (msg) (defun mu4e~hdrs-view-handler (msg)
"Handler function for displaying a message." "Handler function for displaying a message."
(mu4e-view msg mu4e-hdrs-buffer)) (mu4e-view msg mu4e~hdrs-buffer))
(defun mu4e-hdrs-update-handler (msg is-move) (defun mu4e~hdrs-update-handler (msg is-move)
"Update handler, will be called when a message has been updated "Update handler, will be called when a message has been updated
in the database. This function will update the current list of in the database. This function will update the current list of
headers." headers."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(let* ((docid (plist-get msg :docid)) (let* ((docid (plist-get msg :docid))
(point (mu4e--docid-pos docid))) (point (mu4e~docid-pos docid)))
(when point ;; is the message present in this list? (when point ;; is the message present in this list?
;; if it's marked, unmark it now ;; if it's marked, unmark it now
@ -99,11 +99,11 @@ headers."
;; search results) ;; search results)
;; but since we still have the search results, re-use those ;; but since we still have the search results, re-use those
(plist-put msg :thread (plist-put msg :thread
(mu4e--field-for-docid docid :thread)) (mu4e~field-for-docid docid :thread))
;; first, remove the old one (otherwise, we'd have two headers with ;; first, remove the old one (otherwise, we'd have two headers with
;; the same docid... ;; the same docid...
(mu4e-hdrs-remove-handler docid) (mu4e~hdrs-remove-handler docid)
;; if we we're actually viewing this message (in mu4e-view mode), we ;; if we we're actually viewing this message (in mu4e-view mode), we
;; update the `mu4e-current-msg' there as well; that way, the flags can ;; update the `mu4e-current-msg' there as well; that way, the flags can
@ -113,30 +113,30 @@ headers."
(when (and viewbuf (buffer-live-p viewbuf)) (when (and viewbuf (buffer-live-p viewbuf))
(with-current-buffer viewbuf (with-current-buffer viewbuf
(when (eq docid (plist-get mu4e-current-msg :docid)) (when (eq docid (plist-get mu4e-current-msg :docid))
(mu4e-view msg mu4e-hdrs-buffer))))) (mu4e-view msg mu4e~hdrs-buffer)))))
;; now, if this update was about *moving* a message, we don't show it ;; now, if this update was about *moving* a message, we don't show it
;; anymore (of course, we cannot be sure if the message really no ;; anymore (of course, we cannot be sure if the message really no
;; longer matches the query, but this seem a good heuristic. ;; longer matches the query, but this seem a good heuristic.
;; if it was only a flag-change, show the message with its updated flags. ;; if it was only a flag-change, show the message with its updated flags.
(unless is-move (unless is-move
(mu4e-hdrs-header-handler msg point)) (mu4e~hdrs-header-handler msg point))
;; attempt to highlight the corresponding line and make it visible ;; attempt to highlight the corresponding line and make it visible
(mu4e-hdrs-highlight docid)))))) (mu4e~hdrs-highlight docid))))))
(defun mu4e-hdrs-remove-handler (docid) (defun mu4e~hdrs-remove-handler (docid)
"Remove handler, will be called when a message has been removed "Remove handler, will be called when a message has been removed
from the database. This function will hide the removed message from from the database. This function will hide the removed message from
the current list of headers." the current list of headers."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(mu4e-hdrs-remove-header docid)))) (mu4e~hdrs-remove-header docid))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e-hdrs-contact-str (contacts) (defun mu4e~hdrs-contact-str (contacts)
"Turn the list of contacts CONTACTS (with elements (NAME . EMAIL) "Turn the list of contacts CONTACTS (with elements (NAME . EMAIL)
into a string." into a string."
(mapconcat (mapconcat
@ -161,10 +161,10 @@ into a string."
(duplicate "= ") (duplicate "= ")
(t "| ")))))) (t "| "))))))
(defun mu4e-hdrs-header-handler (msg &optional point) (defun mu4e~hdrs-header-handler (msg &optional point)
"Create a one line description of MSG in this buffer, at POINT, "Create a one line description of MSG in this buffer, at POINT,
if provided, or at the end of the buffer otherwise." if provided, or at the end of the buffer otherwise."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(let* ((docid (plist-get msg :docid)) (let* ((docid (plist-get msg :docid))
(line (line
(mapconcat (mapconcat
@ -178,7 +178,7 @@ if provided, or at the end of the buffer otherwise."
(mu4e-thread-prefix (plist-get msg :thread)) (mu4e-thread-prefix (plist-get msg :thread))
val)) val))
((:maildir :path) val) ((:maildir :path) val)
((:to :from :cc :bcc) (mu4e-hdrs-contact-str val)) ((:to :from :cc :bcc) (mu4e~hdrs-contact-str val))
;; if we (ie. `user-mail-address' is the 'From', show ;; if we (ie. `user-mail-address' is the 'From', show
;; 'To', otherwise show From ;; 'To', otherwise show From
(:from-or-to (:from-or-to
@ -187,8 +187,8 @@ if provided, or at the end of the buffer otherwise."
(if (and from (string-match (if (and from (string-match
mu4e-user-mail-address-regexp from)) mu4e-user-mail-address-regexp from))
(concat "To " (concat "To "
(mu4e-hdrs-contact-str (plist-get msg :to))) (mu4e~hdrs-contact-str (plist-get msg :to)))
(mu4e-hdrs-contact-str from-lst)))) (mu4e~hdrs-contact-str from-lst))))
(:date (format-time-string mu4e-headers-date-format val)) (:date (format-time-string mu4e-headers-date-format val))
(:flags (mu4e-flags-to-string val)) (:flags (mu4e-flags-to-string val))
(:size (mu4e-display-size val)) (:size (mu4e-display-size val))
@ -210,13 +210,13 @@ if provided, or at the end of the buffer otherwise."
(propertize line 'face 'mu4e-header-face))))) (propertize line 'face 'mu4e-header-face)))))
;; now, append the header line ;; now, append the header line
(mu4e-hdrs-add-header line docid point msg)))) (mu4e~hdrs-add-header line docid point msg))))
(defun mu4e-hdrs-found-handler (count) (defun mu4e~hdrs-found-handler (count)
"Create a one line description of the number of headers found "Create a one line description of the number of headers found
after the end of the search results." after the end of the search results."
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(save-excursion (save-excursion
(goto-char (point-max)) (goto-char (point-max))
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
@ -228,7 +228,7 @@ after the end of the search results."
(message "Found %d matching message%s" (message "Found %d matching message%s"
count (if (= 1 count) "" "s")) count (if (= 1 count) "" "s"))
;; highlight the first message ;; highlight the first message
(mu4e-hdrs-highlight (mu4e--docid-at-point (point-min))))))))) (mu4e~hdrs-highlight (mu4e~docid-at-point (point-min)))))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -240,11 +240,11 @@ after the end of the search results."
"Keymap for *mu4e-headers* buffers.") "Keymap for *mu4e-headers* buffers.")
(unless mu4e-hdrs-mode-map (unless mu4e-hdrs-mode-map
;; add some quick funcs so our key descriptions below are shorter ;; add some quick funcs so our key descriptions below are shorter
(defun mu4e--hdrs-mark-trash()(interactive)(mu4e-hdrs-mark-and-next 'trash)) (defun mu4e~hdrs-mark-trash()(interactive)(mu4e-hdrs-mark-and-next 'trash))
(defun mu4e--hdrs-mark-delete()(interactive)(mu4e-hdrs-mark-and-next 'delete)) (defun mu4e~hdrs-mark-delete()(interactive)(mu4e-hdrs-mark-and-next 'delete))
(defun mu4e--hdrs-mark-unmark()(interactive)(mu4e-hdrs-mark-and-next 'unmark)) (defun mu4e~hdrs-mark-unmark()(interactive)(mu4e-hdrs-mark-and-next 'unmark))
(defun mu4e--hdrs-mark-read()(interactive)(mu4e-hdrs-mark-and-next 'read)) (defun mu4e~hdrs-mark-read()(interactive)(mu4e-hdrs-mark-and-next 'read))
(defun mu4e--hdrs-mark-unread()(interactive)(mu4e-hdrs-mark-and-next 'unread)) (defun mu4e~hdrs-mark-unread()(interactive)(mu4e-hdrs-mark-and-next 'unread))
(setq mu4e-hdrs-mode-map (setq mu4e-hdrs-mode-map
(let ((map (make-sparse-keymap))) (let ((map (make-sparse-keymap)))
@ -254,8 +254,8 @@ after the end of the search results."
(define-key map "b" 'mu4e-search-bookmark) (define-key map "b" 'mu4e-search-bookmark)
(define-key map "B" 'mu4e-search-bookmark-edit-first) (define-key map "B" 'mu4e-search-bookmark-edit-first)
(define-key map "q" 'mu4e-hdrs-kill-buffer-and-window) (define-key map "q" 'mu4e~hdrs-kill-buffer-and-window)
(define-key map "z" 'mu4e-hdrs-kill-buffer-and-window) (define-key map "z" 'mu4e~hdrs-kill-buffer-and-window)
(define-key map "r" 'mu4e-rerun-search) (define-key map "r" 'mu4e-rerun-search)
(define-key map "g" 'mu4e-rerun-search) ;; for compatibility (define-key map "g" 'mu4e-rerun-search) ;; for compatibility
@ -271,16 +271,16 @@ after the end of the search results."
(define-key map "y" 'mu4e-select-other-view) (define-key map "y" 'mu4e-select-other-view)
;; marking/unmarking ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; marking/unmarking ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-key map (kbd "<backspace>") 'mu4e--hdrs-mark-trash) (define-key map (kbd "<backspace>") 'mu4e~hdrs-mark-trash)
(define-key map (kbd "d") 'mu4e--hdrs-mark-trash) (define-key map (kbd "d") 'mu4e~hdrs-mark-trash)
(define-key map (kbd "<delete>") 'mu4e--hdrs-mark-delete) (define-key map (kbd "<delete>") 'mu4e~hdrs-mark-delete)
(define-key map (kbd "<deletechar>") 'mu4e--hdrs-mark-delete) (define-key map (kbd "<deletechar>") 'mu4e~hdrs-mark-delete)
(define-key map (kbd "D") 'mu4e--hdrs-mark-delete) (define-key map (kbd "D") 'mu4e~hdrs-mark-delete)
(define-key map (kbd "o") 'mu4e--hdrs-mark-unread) (define-key map (kbd "o") 'mu4e~hdrs-mark-unread)
(define-key map (kbd "r") 'mu4e--hdrs-mark-read) (define-key map (kbd "r") 'mu4e~hdrs-mark-read)
(define-key map (kbd "u") 'mu4e--hdrs-mark-unmark) (define-key map (kbd "u") 'mu4e~hdrs-mark-unmark)
(define-key map "m" 'mu4e-hdrs-mark-for-move-and-next) (define-key map "m" 'mu4e-hdrs-mark-for-move-and-next)
@ -309,8 +309,8 @@ after the end of the search results."
(let ((menumap (make-sparse-keymap "Headers"))) (let ((menumap (make-sparse-keymap "Headers")))
(define-key map [menu-bar headers] (cons "Headers" menumap)) (define-key map [menu-bar headers] (cons "Headers" menumap))
(define-key menumap [mu4e-hdrs-kill-buffer-and-window] (define-key menumap [mu4e~hdrs-kill-buffer-and-window]
'("Quit view" . mu4e-hdrs-kill-buffer-and-window)) '("Quit view" . mu4e~hdrs-kill-buffer-and-window))
(define-key menumap [display-help] '("Help" . mu4e-display-manual)) (define-key menumap [display-help] '("Help" . mu4e-display-manual))
(define-key menumap [sepa0] '("--")) (define-key menumap [sepa0] '("--"))
@ -318,16 +318,16 @@ after the end of the search results."
(define-key menumap [execute-marks] '("Execute marks" (define-key menumap [execute-marks] '("Execute marks"
. mu4e-mark-execute-all)) . mu4e-mark-execute-all))
(define-key menumap [unmark-all] '("Unmark all" . mu4e-mark-unmark-all)) (define-key menumap [unmark-all] '("Unmark all" . mu4e-mark-unmark-all))
(define-key menumap [unmark] '("Unmark" . mu4e--hdrs-mark-unmark)) (define-key menumap [unmark] '("Unmark" . mu4e~hdrs-mark-unmark))
(define-key menumap [mark-as-read] '("Mark as read" . mu4e--hdrs-mark-read)) (define-key menumap [mark-as-read] '("Mark as read" . mu4e~hdrs-mark-read))
(define-key menumap [mark-as-unread] (define-key menumap [mark-as-unread]
'("Mark as unread" . mu4e--hdrs-mark-unread)) '("Mark as unread" . mu4e~hdrs-mark-unread))
(define-key menumap [mark-delete] (define-key menumap [mark-delete]
'("Mark for deletion" . mu4e--hdrs-mark-delete)) '("Mark for deletion" . mu4e~hdrs-mark-delete))
(define-key menumap [mark-trash] (define-key menumap [mark-trash]
'("Mark for trash" . mu4e--hdrs-mark-trash)) '("Mark for trash" . mu4e~hdrs-mark-trash))
(define-key menumap [mark-move] (define-key menumap [mark-move]
'("Mark for move" . mu4e-hdrs-mark-for-move-and-next)) '("Mark for move" . mu4e-hdrs-mark-for-move-and-next))
(define-key menumap [sepa1] '("--")) (define-key menumap [sepa1] '("--"))
@ -359,8 +359,8 @@ after the end of the search results."
(use-local-map mu4e-hdrs-mode-map) (use-local-map mu4e-hdrs-mode-map)
(make-local-variable 'mu4e-last-expr) (make-local-variable 'mu4e-last-expr)
(make-local-variable 'mu4e-hdrs-proc) (make-local-variable 'mu4e~hdrs-proc)
(make-local-variable 'mu4e--highlighted-docid) (make-local-variable 'mu4e~highlighted-docid)
(make-local-variable 'global-mode-string) (make-local-variable 'global-mode-string)
(make-local-variable 'hl-line-face) (make-local-variable 'hl-line-face)
@ -370,13 +370,13 @@ after the end of the search results."
buffer-undo-list t ;; don't record undo information buffer-undo-list t ;; don't record undo information
overwrite-mode 'overwrite-mode-binary overwrite-mode 'overwrite-mode-binary
hl-line-face 'mu4e-header-highlight-face) hl-line-face 'mu4e-header-highlight-face)
(mu4e--mark-initialize) ;; initialize the marking subsystem (mu4e~mark-initialize) ;; initialize the marking subsystem
(hl-line-mode 1) (hl-line-mode 1)
(setq header-line-format (setq header-line-format
(cons (cons
(make-string (make-string
(+ (length mu4e-hdrs-fringe) (floor (fringe-columns 'left t))) ?\s) (+ (length mu4e~hdrs-fringe) (floor (fringe-columns 'left t))) ?\s)
(map 'list (map 'list
(lambda (item) (lambda (item)
(let ((field (cdr (assoc (car item) mu4e-header-names))) (let ((field (cdr (assoc (car item) mu4e-header-names)))
@ -391,22 +391,22 @@ after the end of the search results."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; higlighting ;;; higlighting
(defvar mu4e--highlighted-docid nil (defvar mu4e~highlighted-docid nil
"*internal* The highlighted docid") "*internal* The highlighted docid")
(defun mu4e-hdrs-highlight (docid) (defun mu4e~hdrs-highlight (docid)
"Highlight the header with DOCID, or do nothing if it's not "Highlight the header with DOCID, or do nothing if it's not
found. Also, unhighlight any previously highlighted headers." found. Also, unhighlight any previously highlighted headers."
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(save-excursion (save-excursion
;; first, unhighlight the previously highlighted docid, if any ;; first, unhighlight the previously highlighted docid, if any
(when (and mu4e--highlighted-docid (when (and mu4e~highlighted-docid
(mu4e--goto-docid mu4e--highlighted-docid)) (mu4e~goto-docid mu4e~highlighted-docid))
(hl-line-unhighlight)) (hl-line-unhighlight))
;; now, highlight the new one ;; now, highlight the new one
(when (mu4e--goto-docid docid) (when (mu4e~goto-docid docid)
(hl-line-highlight))) (hl-line-highlight)))
(setq mu4e--highlighted-docid docid))) (setq mu4e~highlighted-docid docid)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -414,7 +414,7 @@ found. Also, unhighlight any previously highlighted headers."
"When there is a visible window for the headers buffer, make sure "When there is a visible window for the headers buffer, make sure
to select it. This is needed when adding new headers, otherwise to select it. This is needed when adding new headers, otherwise
adding a lot of new headers looks really choppy." adding a lot of new headers looks really choppy."
(let ((win (get-buffer-window mu4e-hdrs-buffer))) (let ((win (get-buffer-window mu4e~hdrs-buffer)))
(when win (select-window win)))) (when win (select-window win))))
;;;; headers in the buffer are prefixed by an invisible string with the docid ;;;; headers in the buffer are prefixed by an invisible string with the docid
@ -423,12 +423,12 @@ adding a lot of new headers looks really choppy."
;;;; is used for quickly finding a certain header, the latter for retrieving the ;;;; is used for quickly finding a certain header, the latter for retrieving the
;;;; docid at point without string matching etc. ;;;; docid at point without string matching etc.
(defun mu4e--docid-cookie (docid) (defun mu4e~docid-cookie (docid)
"Create an invisible string containing DOCID; this is to be used "Create an invisible string containing DOCID; this is to be used
at the beginning of lines to identify headers." at the beginning of lines to identify headers."
(propertize (format "%d\004" docid) 'docid docid 'invisible t)) (propertize (format "%d\004" docid) 'docid docid 'invisible t))
(defun mu4e--docid-at-point (&optional point) (defun mu4e~docid-at-point (&optional point)
"Get the docid for the header at POINT, or at current (point) if "Get the docid for the header at POINT, or at current (point) if
nil. Returns the docid, or nil if there is none." nil. Returns the docid, or nil if there is none."
(save-excursion (save-excursion
@ -436,7 +436,7 @@ nil. Returns the docid, or nil if there is none."
(goto-char point)) (goto-char point))
(get-text-property (line-beginning-position) 'docid))) (get-text-property (line-beginning-position) 'docid)))
(defun mu4e--goto-docid (docid &optional to-mark) (defun mu4e~goto-docid (docid &optional to-mark)
"Go to the beginning of the line with the header with docid "Go to the beginning of the line with the header with docid
DOCID, or nil if it cannot be found. If the optional TO-MARK is DOCID, or nil if it cannot be found. If the optional TO-MARK is
non-nil, go to the point directly *after* the docid-cookie instead non-nil, go to the point directly *after* the docid-cookie instead
@ -453,27 +453,27 @@ of the beginning of the line."
(setq newpoint (point))))) (setq newpoint (point)))))
newpoint)) ;; return the point, or nil if not found newpoint)) ;; return the point, or nil if not found
(defun mu4e--docid-pos (docid) (defun mu4e~docid-pos (docid)
"Return the pos of the beginning of the line with the header with "Return the pos of the beginning of the line with the header with
docid DOCID, or nil if it cannot be found." docid DOCID, or nil if it cannot be found."
(let ((pos)) (let ((pos))
(save-excursion (save-excursion
(setq pos (mu4e--goto-docid docid))) (setq pos (mu4e~goto-docid docid)))
pos)) pos))
(defun mu4e--field-for-docid (docid field) (defun mu4e~field-for-docid (docid field)
"Get FIELD (a symbol, see `mu4e-headers-names') for the message "Get FIELD (a symbol, see `mu4e-headers-names') for the message
with DOCID which must be present in the headers buffer." with DOCID which must be present in the headers buffer."
(save-excursion (save-excursion
(when (mu4e--goto-docid docid) (when (mu4e~goto-docid docid)
(mu4e-field-at-point field)))) (mu4e-field-at-point field))))
;;;; markers mark headers for ;;;; markers mark headers for
(defun mu4e--mark-header (docid mark) (defun mu4e~mark-header (docid mark)
"(Visually) mark the header for DOCID with character MARK." "(Visually) mark the header for DOCID with character MARK."
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(let ((inhibit-read-only t) (oldpoint (point))) (let ((inhibit-read-only t) (oldpoint (point)))
(unless (mu4e--goto-docid docid) (unless (mu4e~goto-docid docid)
(error "Cannot find message with docid %S" docid)) (error "Cannot find message with docid %S" docid))
;; now, we're at the beginning of the header, looking at ;; now, we're at the beginning of the header, looking at
;; <docid>\004 ;; <docid>\004
@ -484,17 +484,17 @@ with DOCID which must be present in the headers buffer."
;; the area to write the marker. ;; the area to write the marker.
;;(forward-char) ;;(forward-char)
;; clear old marks, and add the new ones. ;; clear old marks, and add the new ones.
(delete-char (length mu4e-hdrs-fringe)) (delete-char (length mu4e~hdrs-fringe))
(insert (propertize mark 'face 'mu4e-hdrs-marks-face) " ") (insert (propertize mark 'face 'mu4e-hdrs-marks-face) " ")
(goto-char oldpoint)))) (goto-char oldpoint))))
(defun mu4e-hdrs-add-header (str docid point &optional msg) (defun mu4e~hdrs-add-header (str docid point &optional msg)
"Add header STR with DOCID to the buffer at POINT if non-nil, or "Add header STR with DOCID to the buffer at POINT if non-nil, or
at (point-max) otherwise. If MSG is not nil, add it as the text-property `msg'." at (point-max) otherwise. If MSG is not nil, add it as the text-property `msg'."
(unless docid (error "Invalid message")) (unless docid (error "Invalid message"))
(when (buffer-live-p mu4e-hdrs-buffer) (when (buffer-live-p mu4e~hdrs-buffer)
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(let ((inhibit-read-only t) (let ((inhibit-read-only t)
(is-first-header (= (point-min) (point-max)))) (is-first-header (= (point-min) (point-max))))
(save-excursion (save-excursion
@ -502,13 +502,13 @@ at (point-max) otherwise. If MSG is not nil, add it as the text-property `msg'."
(insert (insert
(propertize (propertize
(concat (concat
(mu4e--docid-cookie docid) (mu4e~docid-cookie docid)
mu4e-hdrs-fringe str "\n") 'docid docid 'msg msg))))))) mu4e~hdrs-fringe str "\n") 'docid docid 'msg msg)))))))
(defun mu4e-hdrs-remove-header (docid) (defun mu4e~hdrs-remove-header (docid)
"Remove header with DOCID at POINT." "Remove header with DOCID at POINT."
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
(unless (mu4e--goto-docid docid) (unless (mu4e~goto-docid docid)
(error "Cannot find message with docid %S" docid)) (error "Cannot find message with docid %S" docid))
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(delete-region (line-beginning-position) (line-beginning-position 2))))) (delete-region (line-beginning-position) (line-beginning-position 2)))))
@ -555,7 +555,7 @@ current window. "
(interactive) (interactive)
(unless (eq major-mode 'mu4e-hdrs-mode) (unless (eq major-mode 'mu4e-hdrs-mode)
(error "Must be in mu4e-hdrs-mode (%S)" major-mode)) (error "Must be in mu4e-hdrs-mode (%S)" major-mode))
(let* ((docid (mu4e--docid-at-point)) (let* ((docid (mu4e~docid-at-point))
(viewwin (and mu4e-view-buffer (viewwin (and mu4e-view-buffer
(get-buffer-window mu4e-view-buffer)))) (get-buffer-window mu4e-view-buffer))))
(unless docid (error "No message at point.")) (unless docid (error "No message at point."))
@ -581,13 +581,13 @@ current window. "
(erase-buffer) (erase-buffer)
(insert (propertize "Waiting for message..." (insert (propertize "Waiting for message..."
'face 'mu4e-system-face 'intangible t))) 'face 'mu4e-system-face 'intangible t)))
(mu4e-proc-view docid))) (mu4e~proc-view docid)))
(defun mu4e-hdrs-kill-buffer-and-window () (defun mu4e~hdrs-kill-buffer-and-window ()
"Quit the message view and return to the main view." "Quit the message view and return to the main view."
(interactive) (interactive)
(when (mu4e-mark-handle-when-leaving) (when (mu4e-mark-handle-when-leaving)
(mu4e-kill-buffer-and-window mu4e-hdrs-buffer) (mu4e-kill-buffer-and-window mu4e~hdrs-buffer)
(mu4e-main-view))) (mu4e-main-view)))
(defun mu4e-rerun-search () (defun mu4e-rerun-search ()
@ -599,20 +599,20 @@ do a new search."
(mu4e-hdrs-search mu4e-last-expr) (mu4e-hdrs-search mu4e-last-expr)
(call-interactively 'mu4e-search)))) (call-interactively 'mu4e-search))))
(defun mu4e--hdrs-move (lines) (defun mu4e~hdrs-move (lines)
"Move point LINES lines forward (if LINES is positive) or "Move point LINES lines forward (if LINES is positive) or
backward (if LINES is negative). If this succeeds, return the new backward (if LINES is negative). If this succeeds, return the new
docid. Otherwise, return nil." docid. Otherwise, return nil."
(unless (eq major-mode 'mu4e-hdrs-mode) (unless (eq major-mode 'mu4e-hdrs-mode)
(error "Must be in mu4e-hdrs-mode (%S)" major-mode)) (error "Must be in mu4e-hdrs-mode (%S)" major-mode))
(let ((succeeded (= 0 (forward-line lines))) (let ((succeeded (= 0 (forward-line lines)))
(docid (mu4e--docid-at-point))) (docid (mu4e~docid-at-point)))
;; trick to move point, even if this function is called when this window ;; trick to move point, even if this function is called when this window
;; is not visible ;; is not visible
(when docid (when docid
(set-window-point (get-buffer-window mu4e-hdrs-buffer) (point)) (set-window-point (get-buffer-window mu4e~hdrs-buffer) (point))
;; attempt to highlight the new line, display the message ;; attempt to highlight the new line, display the message
(mu4e-hdrs-highlight docid) (mu4e~hdrs-highlight docid)
;; if there already is a visible message view, show the message ;; if there already is a visible message view, show the message
(when (and (buffer-live-p mu4e-view-buffer) (when (and (buffer-live-p mu4e-view-buffer)
(window-live-p (get-buffer-window mu4e-view-buffer))) (window-live-p (get-buffer-window mu4e-view-buffer)))
@ -624,13 +624,13 @@ docid. Otherwise, return nil."
"Move point to the next message header. If this succeeds, return "Move point to the next message header. If this succeeds, return
the new docid. Otherwise, return nil." the new docid. Otherwise, return nil."
(interactive) (interactive)
(mu4e--hdrs-move 1)) (mu4e~hdrs-move 1))
(defun mu4e-prev-header () (defun mu4e-prev-header ()
"Move point to the previous message header. If this succeeds, "Move point to the previous message header. If this succeeds,
return the new docid. Otherwise, return nil." return the new docid. Otherwise, return nil."
(interactive) (interactive)
(mu4e--hdrs-move -1)) (mu4e~hdrs-move -1))
(defun mu4e-jump-to-maildir () (defun mu4e-jump-to-maildir ()
@ -650,18 +650,18 @@ a symbol, one of `reply', `forward', `edit', `new'. All but `new'
take the message at point as input. Symbol `edit' is only allowed take the message at point as input. Symbol `edit' is only allowed
for draft messages." for draft messages."
(interactive) (interactive)
(let ((mu4e-hdrs-buffer (get-buffer-create mu4e-hdrs-buffer-name)) (let ((mu4e~hdrs-buffer (get-buffer-create mu4e~hdrs-buffer-name))
(compose-type (compose-type
(or compose-type (or compose-type
(intern (ido-completing-read "Compose type: " (intern (ido-completing-read "Compose type: "
'("reply" "forward" "edit" "new")))))) '("reply" "forward" "edit" "new"))))))
(with-current-buffer mu4e-hdrs-buffer (with-current-buffer mu4e~hdrs-buffer
;; 'new is special, since it takes no existing message as arg therefore, ;; 'new is special, since it takes no existing message as arg therefore,
;; we don't need to call thec backend, and call the handler *directly* ;; we don't need to call thec backend, and call the handler *directly*
(if (eq compose-type 'new) (if (eq compose-type 'new)
(mu4e-compose-handler 'new) (mu4e-compose-handler 'new)
;; otherwise, we need the doc-id ;; otherwise, we need the doc-id
(let ((docid (mu4e--docid-at-point))) (let ((docid (mu4e~docid-at-point)))
(unless docid (error "No message at point.")) (unless docid (error "No message at point."))
;; note, the first two chars of the line (the mark margin) does *not* ;; note, the first two chars of the line (the mark margin) does *not*
;; have the 'draft property; thus, we check one char before the end of ;; have the 'draft property; thus, we check one char before the end of
@ -678,7 +678,7 @@ for draft messages."
(select-window viewwin))) (select-window viewwin)))
;; talk to the backend ;; talk to the backend
(mu4e-proc-compose compose-type docid)))))) (mu4e~proc-compose compose-type docid))))))
(defun mu4e-compose-reply () (defun mu4e-compose-reply ()
"Reply to the current message." "Reply to the current message."

View File

@ -30,7 +30,7 @@
(require 'mu4e-utils) (require 'mu4e-utils)
;;; marks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; marks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar mu4e--mark-map nil (defvar mu4e~mark-map nil
"Map (hash) of docid->markinfo; when a message is marked, the "Map (hash) of docid->markinfo; when a message is marked, the
information is added here. information is added here.
@ -45,14 +45,14 @@ where
;; happen in the future ;; happen in the future
(defun mu4e--mark-initialize () (defun mu4e~mark-initialize ()
"Initialize the marks subsystem." "Initialize the marks subsystem."
(make-local-variable 'mu4e--mark-map) (make-local-variable 'mu4e~mark-map)
(setq mu4e--mark-map (make-hash-table :size 16 :rehash-size 2))) (setq mu4e~mark-map (make-hash-table :size 16 :rehash-size 2)))
(defun mu4e--mark-clear () (defun mu4e~mark-clear ()
"Clear the marks subsystem." "Clear the marks subsystem."
(clrhash mu4e--mark-map)) (clrhash mu4e~mark-map))
(defun mu4e-mark-at-point (mark &optional target) (defun mu4e-mark-at-point (mark &optional target)
@ -72,7 +72,7 @@ The following marks are available, and the corresponding props:
`unread' n mark the message as unread `unread' n mark the message as unread
`unmark' n unmark this message" `unmark' n unmark this message"
(interactive) (interactive)
(let* ((docid (mu4e--docid-at-point)) (let* ((docid (mu4e~docid-at-point))
(markkar (markkar
(case mark ;; the visual mark (case mark ;; the visual mark
('move "m") ('move "m")
@ -84,25 +84,25 @@ The following marks are available, and the corresponding props:
(t (error "Invalid mark %S" mark))))) (t (error "Invalid mark %S" mark)))))
(unless docid (error "No message on this line")) (unless docid (error "No message on this line"))
(save-excursion (save-excursion
(when (mu4e--mark-header docid markkar)) (when (mu4e~mark-header docid markkar))
;; update the hash -- remove everything current, and if add the new stuff, ;; update the hash -- remove everything current, and if add the new stuff,
;; unless we're unmarking ;; unless we're unmarking
(remhash docid mu4e--mark-map) (remhash docid mu4e~mark-map)
;; remove possible overlays ;; remove possible overlays
(remove-overlays (line-beginning-position) (line-end-position)) (remove-overlays (line-beginning-position) (line-end-position))
;; now, let's set a mark (unless we were unmarking) ;; now, let's set a mark (unless we were unmarking)
(unless (eql mark 'unmark) (unless (eql mark 'unmark)
(puthash docid (list mark target) mu4e--mark-map) (puthash docid (list mark target) mu4e~mark-map)
;; when we have a target (ie., when moving), show the target folder in ;; when we have a target (ie., when moving), show the target folder in
;; an overlay ;; an overlay
(when target (when target
(let* ((targetstr (propertize (concat "-> " target " ") (let* ((targetstr (propertize (concat "-> " target " ")
'face 'mu4e-system-face)) 'face 'mu4e-system-face))
;; mu4e-goto-docid docid t will take us just after the docid cookie ;; mu4e-goto-docid docid t \will take us just after the docid cookie
;; and then we skip the mu4e-hdrs-fringe ;; and then we skip the mu4e~hdrs-fringe
(start (+ (length mu4e-hdrs-fringe) (start (+ (length mu4e~hdrs-fringe)
(mu4e--goto-docid docid t))) (mu4e~goto-docid docid t)))
(overlay (make-overlay start (+ start (length targetstr))))) (overlay (make-overlay start (+ start (length targetstr)))))
(overlay-put overlay 'display targetstr) (overlay-put overlay 'display targetstr)
docid)))))) docid))))))
@ -129,7 +129,7 @@ headers in the region."
the region, for moving to maildir TARGET. If target is not the region, for moving to maildir TARGET. If target is not
provided, function asks for it." provided, function asks for it."
(interactive) (interactive)
(unless (mu4e--docid-at-point) (unless (mu4e~docid-at-point)
(error "No message at point.")) (error "No message at point."))
(let* ((target (or target (mu4e-ask-maildir "Move message to: "))) (let* ((target (or target (mu4e-ask-maildir "Move message to: ")))
(target (if (string= (substring target 0 1) "/") (target (if (string= (substring target 0 1) "/")
@ -139,7 +139,7 @@ provided, function asks for it."
(when (or (file-directory-p fulltarget) (when (or (file-directory-p fulltarget)
(and (yes-or-no-p (and (yes-or-no-p
(format "%s does not exist. Create now?" fulltarget)) (format "%s does not exist. Create now?" fulltarget))
(mu4e-proc-mkdir fulltarget))) (mu4e~proc-mkdir fulltarget)))
(mu4e-mark-set 'move target)))) (mu4e-mark-set 'move target))))
@ -158,45 +158,45 @@ work well.
If NO-CONFIRMATION is non-nil, do not ask the user for If NO-CONFIRMATION is non-nil, do not ask the user for
confirmation." confirmation."
(interactive) (interactive)
(if (zerop (hash-table-count mu4e--mark-map)) (if (zerop (hash-table-count mu4e~mark-map))
(message "Nothing is marked") (message "Nothing is marked")
(when (or no-confirmation (when (or no-confirmation
(y-or-n-p (format "Sure you want to execute marks on %d message(s)?" (y-or-n-p (format "Sure you want to execute marks on %d message(s)?"
(hash-table-count mu4e--mark-map)))) (hash-table-count mu4e~mark-map))))
(maphash (maphash
(lambda (docid val) (lambda (docid val)
(let ((mark (nth 0 val)) (target (nth 1 val))) (let ((mark (nth 0 val)) (target (nth 1 val)))
(case mark (case mark
(move (mu4e-proc-move docid target)) (move (mu4e~proc-move docid target))
(read (mu4e-proc-move docid nil "+S-u-N")) (read (mu4e~proc-move docid nil "+S-u-N"))
(unread (mu4e-proc-move docid nil "-S+u")) (unread (mu4e~proc-move docid nil "-S+u"))
(trash (trash
(unless mu4e-trash-folder (unless mu4e-trash-folder
(error "`mu4e-trash-folder' not set")) (error "`mu4e-trash-folder' not set"))
(mu4e-proc-move docid mu4e-trash-folder "+T")) (mu4e~proc-move docid mu4e-trash-folder "+T"))
(delete (mu4e-proc-remove docid))))) (delete (mu4e~proc-remove docid)))))
mu4e--mark-map) mu4e~mark-map)
(mu4e-mark-unmark-all) (mu4e-mark-unmark-all)
(message nil)))) (message nil))))
(defun mu4e-mark-unmark-all () (defun mu4e-mark-unmark-all ()
"Unmark all marked messages." "Unmark all marked messages."
(interactive) (interactive)
(when (zerop (hash-table-count mu4e--mark-map)) (when (zerop (hash-table-count mu4e~mark-map))
(error "Nothing is marked")) (error "Nothing is marked"))
(maphash (maphash
(lambda (docid val) (lambda (docid val)
(save-excursion (save-excursion
(when (mu4e--goto-docid docid) (when (mu4e~goto-docid docid)
(mu4e-mark-set 'unmark)))) (mu4e-mark-set 'unmark))))
mu4e--mark-map) mu4e~mark-map)
;; in any case, clear the marks map ;; in any case, clear the marks map
(mu4e--mark-clear)) (mu4e~mark-clear))
(defun mu4e-mark-docid-marked-p (docid) (defun mu4e-mark-docid-marked-p (docid)
"Is the given docid marked?" "Is the given docid marked?"
(when (gethash docid mu4e--mark-map) t)) (when (gethash docid mu4e~mark-map) t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -207,7 +207,7 @@ function is to be called before any further action (like searching,
quiting the buffer) is taken; returning t means 'take the following quiting the buffer) is taken; returning t means 'take the following
action', return nil means 'don't do anything'" action', return nil means 'don't do anything'"
(let ((marknum (let ((marknum
(if mu4e--mark-map (hash-table-count mu4e--mark-map) 0)) (if mu4e~mark-map (hash-table-count mu4e~mark-map) 0))
(what mu4e-headers-leave-behavior)) (what mu4e-headers-leave-behavior))
(unless (or (= marknum 0) (eq what 'ignore) (eq what 'apply)) (unless (or (= marknum 0) (eq what 'ignore) (eq what 'apply))
;; if `mu4e-headers-leave-behavior' is not apply or ignore, ask the user ;; if `mu4e-headers-leave-behavior' is not apply or ignore, ask the user

View File

@ -27,21 +27,18 @@
(require 'mu4e-utils) (require 'mu4e-utils)
(require 'mu4e-meta) (require 'mu4e-meta)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; internal vars ;; internal vars
(defvar mu4e-buf nil "*internal* Buffer for results data.") (defvar mu4e~proc-buf nil "Buffer for results data.")
(defconst mu4e~proc-name "*mu4e-proc*" "Name of the server process, buffer.")
(defvar mu4e~proc-process nil "The mu-server process")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar mu4e-path-docid-map
(make-hash-table :size 32 :rehash-size 2 :test 'equal :weakness nil)
"*internal* hash we use to keep a path=>docid mapping for message
we added ourselves (ie., draft messages), so we can e.g. move them
to the sent folder using their docid")
(defconst mu4e-server-name "*mu4e-server*"
"*internal* Name of the server process, buffer.")
(defun mu4e-start-proc () (defun mu4e~proc-start ()
"Start the mu server process." "Start the mu server process."
(unless (file-executable-p mu4e-mu-binary) (unless (file-executable-p mu4e-mu-binary)
(error (format "`mu4e-mu-binary' (%S) not found" mu4e-mu-binary))) (error (format "`mu4e-mu-binary' (%S) not found" mu4e-mu-binary)))
@ -49,61 +46,61 @@ to the sent folder using their docid")
(args '("server")) (args '("server"))
(args (append args (when mu4e-mu-home (args (append args (when mu4e-mu-home
(list (concat "--muhome=" mu4e-mu-home)))))) (list (concat "--muhome=" mu4e-mu-home))))))
(setq mu4e-buf "") (setq mu4e~proc-buf "")
(setq mu4e-mu-proc (apply 'start-process (setq mu4e~proc-process (apply 'start-process
mu4e-server-name mu4e-server-name mu4e~proc-name mu4e~proc-name
mu4e-mu-binary args)) mu4e-mu-binary args))
;; register a function for (:info ...) sexps ;; register a function for (:info ...) sexps
(when mu4e-mu-proc (when mu4e~proc-process
(set-process-query-on-exit-flag mu4e-mu-proc nil) (set-process-query-on-exit-flag mu4e~proc-process nil)
(set-process-coding-system mu4e-mu-proc 'binary 'utf-8-unix) (set-process-coding-system mu4e~proc-process 'binary 'utf-8-unix)
(set-process-filter mu4e-mu-proc 'mu4e-proc-filter) (set-process-filter mu4e~proc-process 'mu4e~proc-filter)
(set-process-sentinel mu4e-mu-proc 'mu4e-proc-sentinel)))) (set-process-sentinel mu4e~proc-process 'mu4e~proc-sentinel))))
(defun mu4e-kill-proc () (defun mu4e~proc-kill ()
"Kill the mu server process." "Kill the mu server process."
(let* ((buf (get-buffer mu4e-server-name)) (let* ((buf (get-buffer mu4e~proc-name))
(proc (and buf (get-buffer-process buf)))) (proc (and buf (get-buffer-process buf))))
(when proc (when proc
(let ((delete-exited-processes t)) (let ((delete-exited-processes t))
;; the mu server signal handler will make it quit after 'quit' ;; the mu server signal handler will make it quit after 'quit'
(mu4e-proc-send-command "quit")) (mu4e~proc-send-command "quit"))
;; try sending SIGINT (C-c) to process, so it can exit gracefully ;; try sending SIGINT (C-c) to process, so it can exit gracefully
(ignore-errors (ignore-errors
(signal-process proc 'SIGINT)))) (signal-process proc 'SIGINT))))
(setq (setq
mu4e-mu-proc nil mu4e~proc-process nil
mu4e-buf nil)) mu4e~proc-buf nil))
(defun mu4e-proc-eat-sexp-from-buf () (defun mu4e~proc-eat-sexp-from-buf ()
"'Eat' the next s-expression from `mu4e-buf'. `mu4e-buf gets its "'Eat' the next s-expression from `mu4e~proc-buf'. `mu4e~proc-buf gets its
contents from the mu-servers in the following form: contents from the mu-servers in the following form:
\376<len-of-sexp>\376<sexp> \376<len-of-sexp>\376<sexp>
Function returns this sexp, or nil if there was none. `mu4e-buf' is Function returns this sexp, or nil if there was none. `mu4e~proc-buf' is
updated as well, with all processed sexp data removed." updated as well, with all processed sexp data removed."
(when mu4e-buf (when mu4e~proc-buf
;; TODO: maybe try a non-regexp solution? ;; TODO: maybe try a non-regexp solution?
(let* ((b (string-match "\376\\([0-9]+\\)\376" mu4e-buf)) (let* ((b (string-match "\376\\([0-9]+\\)\376" mu4e~proc-buf))
(sexp-len (sexp-len
(when b (string-to-number (match-string 1 mu4e-buf))))) (when b (string-to-number (match-string 1 mu4e~proc-buf)))))
;; does mu4e-buf contain the full sexp? ;; does mu4e~proc-buf contain the full sexp?
(when (and b (>= (length mu4e-buf) (+ sexp-len (match-end 0)))) (when (and b (>= (length mu4e~proc-buf) (+ sexp-len (match-end 0))))
;; clear-up start ;; clear-up start
(setq mu4e-buf (substring mu4e-buf (match-end 0))) (setq mu4e~proc-buf (substring mu4e~proc-buf (match-end 0)))
;; note: we read the input in binary mode -- here, we take the part that ;; note: we read the input in binary mode -- here, we take the part that
;; is the sexp, and convert that to utf-8, before we interpret it. ;; is the sexp, and convert that to utf-8, before we interpret it.
(let ((objcons (let ((objcons
(ignore-errors ;; note: this may fail if we killed the process (ignore-errors ;; note: this may fail if we killed the process
;; in the middle ;; in the middle
(read-from-string (read-from-string
(decode-coding-string (substring mu4e-buf 0 sexp-len) 'utf-8))))) (decode-coding-string (substring mu4e~proc-buf 0 sexp-len) 'utf-8)))))
(when objcons (when objcons
(setq mu4e-buf (substring mu4e-buf sexp-len)) (setq mu4e~proc-buf (substring mu4e~proc-buf sexp-len))
(car objcons))))))) (car objcons)))))))
(defun mu4e-proc-filter (proc str) (defun mu4e~proc-filter (proc str)
"A process-filter for the 'mu server' output; it accumulates the "A process-filter for the 'mu server' output; it accumulates the
strings into valid sexps by checking of the ';;eox' end-of-sexp strings into valid sexps by checking of the ';;eox' end-of-sexp
marker, and then evaluating them. marker, and then evaluating them.
@ -160,8 +157,8 @@ updated as well, with all processed sexp data removed."
(:compose <reply|forward|edit|new> [:original<msg-sexp>] [:include <attach>]) (:compose <reply|forward|edit|new> [:original<msg-sexp>] [:include <attach>])
`mu4e-compose-func'." `mu4e-compose-func'."
(mu4e-log 'misc "* Received %d byte(s)" (length str)) (mu4e-log 'misc "* Received %d byte(s)" (length str))
(setq mu4e-buf (concat mu4e-buf str)) ;; update our buffer (setq mu4e~proc-buf (concat mu4e~proc-buf str)) ;; update our buffer
(let ((sexp (mu4e-proc-eat-sexp-from-buf))) (let ((sexp (mu4e~proc-eat-sexp-from-buf)))
(while sexp (while sexp
(mu4e-log 'from-server "%S" sexp) (mu4e-log 'from-server "%S" sexp)
(cond (cond
@ -227,18 +224,18 @@ updated as well, with all processed sexp data removed."
(t (message "Unexpected data from server [%S]" sexp))) (t (message "Unexpected data from server [%S]" sexp)))
(setq sexp (mu4e-proc-eat-sexp-from-buf))))) (setq sexp (mu4e~proc-eat-sexp-from-buf)))))
;; error codes are defined in src/mu-util.h ;; error codes are defined in src/mu-util.h
;;(defconst mu4e-xapian-empty 19 "Error code: xapian is empty/non-existent") ;;(defconst mu4e-xapian-empty 19 "Error code: xapian is empty/non-existent")
(defun mu4e-proc-sentinel (proc msg) (defun mu4e~proc-sentinel (proc msg)
"Function that will be called when the mu-server process "Function that will be called when the mu-server process
terminates." terminates."
(let ((status (process-status proc)) (code (process-exit-status proc))) (let ((status (process-status proc)) (code (process-exit-status proc)))
(setq mu4e-mu-proc nil) (setq mu4e~proc-process nil)
(setq mu4e-buf "") ;; clear any half-received sexps (setq mu4e~proc-buf "") ;; clear any half-received sexps
(cond (cond
((eq status 'signal) ((eq status 'signal)
(cond (cond
@ -257,13 +254,13 @@ terminates."
(t (t
(message "Something bad happened to the mu server process"))))) (message "Something bad happened to the mu server process")))))
(defun mu4e-proc-send-command (frm &rest args) (defun mu4e~proc-send-command (frm &rest args)
"Send as command to the mu server process; start the process if needed." "Send as command to the mu server process; start the process if needed."
(unless (mu4e-proc-is-running) (unless (mu4e~proc-is-running)
(mu4e-start-proc)) (mu4e~proc-start))
(let ((cmd (apply 'format frm args))) (let ((cmd (apply 'format frm args)))
(mu4e-log 'to-server "%s" cmd) (mu4e-log 'to-server "%s" cmd)
(process-send-string mu4e-mu-proc (concat cmd "\n")))) (process-send-string mu4e~proc-process (concat cmd "\n"))))
(defun mu4e--docid-msgid-param (docid-or-msgid) (defun mu4e--docid-msgid-param (docid-or-msgid)
@ -274,23 +271,23 @@ terminates."
"docid:%d") "docid:%d")
docid-or-msgid)) docid-or-msgid))
(defun mu4e-proc-remove (docid) (defun mu4e~proc-remove (docid)
"Remove message identified by docid. "Remove message identified by docid.
The results are reporter through either (:update ... ) or (:error The results are reporter through either (:update ... ) or (:error
) sexp, which are handled my `mu4e-error-func', respectively." ) sexp, which are handled my `mu4e-error-func', respectively."
(mu4e-proc-send-command "remove docid:%d" docid)) (mu4e~proc-send-command "remove docid:%d" docid))
(defun mu4e-proc-find (query &optional maxnum) (defun mu4e~proc-find (query &optional maxnum)
"Start a database query for QUERY, (optionally) getting up to "Start a database query for QUERY, (optionally) getting up to
MAXNUM results. For each result found, a function is called, MAXNUM results. For each result found, a function is called,
depending on the kind of result. The variables `mu4e-error-func' depending on the kind of result. The variables `mu4e-error-func'
contain the function that will be called for, resp., a contain the function that will be called for, resp., a
message (header row) or an error." message (header row) or an error."
(mu4e-proc-send-command (mu4e~proc-send-command
"find query:\"%s\"%s" query "find query:\"%s\"%s" query
(if maxnum (format " maxnum:%d" maxnum) ""))) (if maxnum (format " maxnum:%d" maxnum) "")))
(defun mu4e-proc-move (docid-or-msgid &optional maildir flags) (defun mu4e~proc-move (docid-or-msgid &optional maildir flags)
"Move message identified by DOCID-OR-MSGID. At least one of "Move message identified by DOCID-OR-MSGID. At least one of
MAILDIR and FLAGS should be specified. Note, even if MAILDIR is MAILDIR and FLAGS should be specified. Note, even if MAILDIR is
nil, this is still a move, since a change in flags still implies nil, this is still a move, since a change in flags still implies
@ -329,30 +326,30 @@ or (:error ) sexp, which are handled my `mu4e-update-func' and
(path (path
(when maildir (when maildir
(format " maildir:\"%s\"" maildir)))) (format " maildir:\"%s\"" maildir))))
(mu4e-proc-send-command "move %s %s %s" (mu4e~proc-send-command "move %s %s %s"
idparam (or flagstr "") (or path "")))) idparam (or flagstr "") (or path ""))))
(defun mu4e-proc-index (path) (defun mu4e~proc-index (path)
"Update the message database for filesystem PATH, which should "Update the message database for filesystem PATH, which should
point to some maildir directory structure." point to some maildir directory structure."
(mu4e-proc-send-command "index path:\"%s\"" path)) (mu4e~proc-send-command "index path:\"%s\"" path))
(defun mu4e-proc-add (path maildir) (defun mu4e~proc-add (path maildir)
"Add the message at PATH to the database, with MAILDIR set to the "Add the message at PATH to the database, with MAILDIR set to the
maildir this message resides in, e.g. '/drafts'; if this works, we maildir this message resides in, e.g. '/drafts'; if this works, we
will receive (:info add :path <path> :docid <docid>)." will receive (:info add :path <path> :docid <docid>)."
(mu4e-proc-send-command "add path:\"%s\" maildir:\"%s\"" (mu4e~proc-send-command "add path:\"%s\" maildir:\"%s\""
path maildir)) path maildir))
(defun mu4e-proc-sent (path maildir) (defun mu4e~proc-sent (path maildir)
"Add the message at PATH to the database, with MAILDIR set to the "Add the message at PATH to the database, with MAILDIR set to the
maildir this message resides in, e.g. '/drafts'; if this works, we maildir this message resides in, e.g. '/drafts'; if this works, we
will receive (:info add :path <path> :docid <docid>)." will receive (:info add :path <path> :docid <docid>)."
(mu4e-proc-send-command "sent path:\"%s\" maildir:\"%s\"" (mu4e~proc-send-command "sent path:\"%s\" maildir:\"%s\""
path maildir)) path maildir))
(defun mu4e-proc-compose (type &optional docid) (defun mu4e~proc-compose (type &optional docid)
"Start composing a message of certain TYPE (a symbol, either "Start composing a message of certain TYPE (a symbol, either
`forward', `reply', `edit' or `new', based on an original `forward', `reply', `edit' or `new', based on an original
message (ie, replying to, forwarding, editing) with DOCID or nil message (ie, replying to, forwarding, editing) with DOCID or nil
@ -364,14 +361,14 @@ for type `new'.
(error "Unsupported compose-type %S" type)) (error "Unsupported compose-type %S" type))
(unless (eq (null docid) (eq type 'new)) (unless (eq (null docid) (eq type 'new))
(error "`new' implies docid not-nil, and vice-versa")) (error "`new' implies docid not-nil, and vice-versa"))
(mu4e-proc-send-command "compose type:%s docid:%d" (mu4e~proc-send-command "compose type:%s docid:%d"
(symbol-name type) docid)) (symbol-name type) docid))
(defun mu4e-proc-mkdir (path) (defun mu4e~proc-mkdir (path)
"Create a new maildir-directory at filesystem PATH." "Create a new maildir-directory at filesystem PATH."
(mu4e-proc-send-command "mkdir path:\"%s\"" path)) (mu4e~proc-send-command "mkdir path:\"%s\"" path))
(defun mu4e-proc-extract (action docid partidx &optional path what param) (defun mu4e~proc-extract (action docid partidx &optional path what param)
"Extract an attachment with index PARTIDX from message with DOCID "Extract an attachment with index PARTIDX from message with DOCID
and perform ACTION on it (as symbol, either `save', `open', `temp') which and perform ACTION on it (as symbol, either `save', `open', `temp') which
mean: mean:
@ -390,19 +387,19 @@ mean:
(format "action:temp docid:%d index:%d what:%s param:\"%s\"" (format "action:temp docid:%d index:%d what:%s param:\"%s\""
docid partidx what param)) docid partidx what param))
(otherwise (error "Unsupported action %S" action)))))) (otherwise (error "Unsupported action %S" action))))))
(mu4e-proc-send-command cmd))) (mu4e~proc-send-command cmd)))
(defun mu4e-proc-ping () (defun mu4e~proc-ping ()
"Sends a ping to the mu server, expecting a (:pong ...) in "Sends a ping to the mu server, expecting a (:pong ...) in
response." response."
(mu4e-proc-send-command "ping")) (mu4e~proc-send-command "ping"))
(defun mu4e-proc-view (docid-or-msgid) (defun mu4e~proc-view (docid-or-msgid)
"Get one particular message based on its DOCID-OR-MSGID (keyword "Get one particular message based on its DOCID-OR-MSGID (keyword
argument). The result will be delivered to the function registered argument). The result will be delivered to the function registered
as `mu4e-message-func'." as `mu4e-message-func'."
(mu4e-proc-send-command "view %s" (mu4e~proc-send-command "view %s"
(mu4e--docid-msgid-param docid-or-msgid))) (mu4e--docid-msgid-param docid-or-msgid)))
(provide 'mu4e-proc) (provide 'mu4e-proc)

View File

@ -38,7 +38,7 @@ dir already existed, or has been created, nil otherwise."
(cond (cond
((file-directory-p dir) t) ((file-directory-p dir) t)
((yes-or-no-p (format "%s does not exist yes. Create now?" dir)) ((yes-or-no-p (format "%s does not exist yes. Create now?" dir))
(mu4e-proc-mkdir dir)) (mu4e~proc-mkdir dir))
(t nil))) (t nil)))
(defun mu4e-check-requirements () (defun mu4e-check-requirements ()
@ -287,6 +287,36 @@ Also see `mu/flags-to-string'.
((< size 1000) (format "%d" size)) ((< size 1000) (format "%d" size))
(t (propertize "?" 'face 'mu4e-system-face)))) (t (propertize "?" 'face 'mu4e-system-face))))
;; functions for org-contacts
(defun mu4e-view-snarf-from (name-or-email)
"Get the From:-data for the current message; NAME-OR-EMAIL should
be a symbol 'name or 'email to get the corresponding field. If the
field is not found, \"\" is returned.
You can use this with e.g. org-contact with a template like:
(\"c\" \"Contacts\" entry (file \"~/Org/contacts.org\")
\"* %(mu4e-view-snarf-from 'name)
:PROPERTIES:
:EMAIL: %(mu4e-view-snarf-from 'email)
:END:\")))
See the `org-contacts' documentation for more details."
;; FIXME: we need to explictly go to some view buffer, since when using this
;; from org-capture, we'll be taken to the capture buffer instead.
(with-current-buffer mu4e-view-buffer-name
(unless (eq major-mode 'mu4e-view-mode)
(error "Not in mu4e-view mode."))
(unless mu4e-current-msg
(error "No current message."))
(let ((from (car-safe (plist-get mu4e-current-msg :from))))
(cond
((not from) "") ;; nothing found
((eq name-or-email 'name)
(or (car-safe from) ""))
((eq name-or-email 'email)
(or (cdr-safe from) ""))
(t (error "Not supported: %S" name-or-email))))))
(defun mu4e-body-text (msg) (defun mu4e-body-text (msg)
"Get the body in text form for this message, which is either :body-txt, "Get the body in text form for this message, which is either :body-txt,
@ -350,7 +380,7 @@ processing takes part in the background, unless buf is non-nil."
(message nil) (message nil)
;; there may be an error, give the user up to 5 seconds to check ;; there may be an error, give the user up to 5 seconds to check
(when maybe-error (when maybe-error
(sit-for 5)) (sit-for 5))
(mu4e~proc-index mu4e-maildir) (mu4e~proc-index mu4e-maildir)
(let ((buf (process-buffer proc))) (let ((buf (process-buffer proc)))
(when (buffer-live-p buf) (when (buffer-live-p buf)
@ -497,7 +527,7 @@ that has a live window), and vice versa."
(cond (cond
((eq major-mode 'mu4e-hdrs-mode) ((eq major-mode 'mu4e-hdrs-mode)
mu4e-view-buffer) mu4e-view-buffer)
((eq major-mode 'mu4e-view-mode) ((eq major-mode 'mu4e-view-mode)
mu4e~hdrs-buffer))) mu4e~hdrs-buffer)))
(other-win (and other-buf (get-buffer-window other-buf)))) (other-win (and other-buf (get-buffer-window other-buf))))
(if (window-live-p other-win) (if (window-live-p other-win)
@ -526,11 +556,7 @@ that has a live window), and vice versa."
"Handler function for (:info ...) sexps received from the server "Handler function for (:info ...) sexps received from the server
process." process."
(let ((type (plist-get info :info))) (let ((type (plist-get info :info)))
(cond (cond
((eq type 'add)
;; update our path=>docid map; we use this when composing messages to
;; add draft messages to the db, so when we're sending them, we can move
;; to the sent folder using the `mu4e-proc-move'.
((eq type 'add) t) ;; do nothing ((eq type 'add) t) ;; do nothing
((eq type 'index) ((eq type 'index)
(if (eq (plist-get info :status) 'running) (if (eq (plist-get info :status) 'running)
@ -555,9 +581,9 @@ process."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar mu4e-update-timer nil (defvar mu4e-update-timer nil
"*internal* The mu4e update timer.") "*internal* The mu4e update timer.")
(defun mu4e~proc-is-running () (defun mu4e~proc-is-running ()
"Whether the mu process is running." "Whether the mu process is running."
(and mu4e~proc-process (eq (process-status mu4e~proc-process) 'run))) (and mu4e~proc-process (eq (process-status mu4e~proc-process) 'run)))
@ -567,7 +593,7 @@ server has the expected values. If keyword argument :hide-ui is
server has the expected values. If keyword argument :hide-ui is server has the expected values. If keyword argument :hide-ui is
non-nil, don't show the UI." non-nil, don't show the UI."
(interactive) (interactive)
;; if we're already running, simply go to the main view ;; if we're already running, simply go to the main view
(if (mu4e~proc-is-running) (if (mu4e~proc-is-running)
(unless hide-ui (unless hide-ui
(mu4e-main-view)) (mu4e-main-view))
@ -594,7 +620,7 @@ non-nil, don't show the UI."
0 mu4e-update-interval 'mu4e-update-mail))) 0 mu4e-update-interval 'mu4e-update-mail)))
(message "Started mu4e with %d message%s in store" (message "Started mu4e with %d message%s in store"
doccount (if (= doccount 1) "" "s"))))) doccount (if (= doccount 1) "" "s")))))
;; send the ping ;; send the ping
(mu4e~proc-ping)))))) (mu4e~proc-ping))))))
(defun mu4e-quit() (defun mu4e-quit()
@ -604,7 +630,7 @@ non-nil, don't show the UI."
(message nil) (message nil)
(when mu4e-update-timer (when mu4e-update-timer
(cancel-timer mu4e-update-timer) (cancel-timer mu4e-update-timer)
(setq mu4e-update-timer nil)) (setq mu4e-update-timer nil))
(mu4e~proc-kill) (mu4e~proc-kill)
(kill-buffer))) (kill-buffer)))

View File

@ -483,9 +483,9 @@ in which case it will be equal to `:to'.)")
;; headers ;; headers
(defvar mu4e-last-expr nil "*internal* The most recent search expression.") (defvar mu4e-last-expr nil "*internal* The most recent search expression.")
(defconst mu4e-hdrs-buffer-name "*mu4e-headers*" (defconst mu4e~hdrs-buffer-name "*mu4e-headers*"
"*internal* Name of the buffer for message headers.") "*internal* Name of the buffer for message headers.")
(defvar mu4e-hdrs-buffer nil "*internal* Buffer for message headers") (defvar mu4e~hdrs-buffer nil "*internal* Buffer for message headers")
;; view ;; view
(defconst mu4e-view-buffer-name "*mu4e-view*" (defconst mu4e-view-buffer-name "*mu4e-view*"
@ -503,10 +503,6 @@ viewed in view mode.")
(defconst mu4e-log-buffer-name "*mu4e-log*" (defconst mu4e-log-buffer-name "*mu4e-log*"
"*internal* Name of the logging buffer.") "*internal* Name of the logging buffer.")
(defvar mu4e-mu-proc nil "*internal* The mu-server process")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; misc other stuff ;; misc other stuff
@ -523,66 +519,66 @@ viewed in view mode.")
;; our handlers funcs ;; our handlers funcs
;; these handler funcs define what happens when we receive a certain message ;; these handler funcs define what happens when we receive a certain message
;; from the server ;; from the server
(defun mu4e--default-handler (&rest args) (defun mu4e~default-handler (&rest args)
"*internal* Dummy handler function." "*internal* Dummy handler function."
(error "Not handled: %S" args)) (error "Not handled: %S" args))
(defvar mu4e-error-func 'mu4e--default-handler (defvar mu4e-error-func 'mu4e~default-handler
"A function called for each error returned from the server "A function called for each error returned from the server
process; the function is passed an error plist as argument. See process; the function is passed an error plist as argument. See
`mu4e-proc-filter' for the format.") `mu4e~proc-filter' for the format.")
(defvar mu4e-update-func 'mu4e--default-handler (defvar mu4e-update-func 'mu4e~default-handler
"A function called for each :update sexp returned from the server "A function called for each :update sexp returned from the server
process; the function is passed a msg sexp as argument. See process; the function is passed a msg sexp as argument. See
`mu4e-proc-filter' for the format.") `mu4e~proc-filter' for the format.")
(defvar mu4e-remove-func 'mu4e--default-handler (defvar mu4e-remove-func 'mu4e~default-handler
"A function called for each :remove sexp returned from the server "A function called for each :remove sexp returned from the server
process, when some message has been deleted. The function is passed process, when some message has been deleted. The function is passed
the docid of the removed message.") the docid of the removed message.")
(defvar mu4e-sent-func 'mu4e--default-handler (defvar mu4e-sent-func 'mu4e~default-handler
"A function called for each :sent sexp returned from the server "A function called for each :sent sexp returned from the server
process, when some message has been sent. The function is passed process, when some message has been sent. The function is passed
the docid and the draft-path of the sent message.") the docid and the draft-path of the sent message.")
(defvar mu4e-view-func 'mu4e--default-handler (defvar mu4e-view-func 'mu4e~default-handler
"A function called for each single message sexp returned from the "A function called for each single message sexp returned from the
server process. The function is passed a message sexp as server process. The function is passed a message sexp as
argument. See `mu4e-proc-filter' for the format.") argument. See `mu4e~proc-filter' for the format.")
(defvar mu4e-header-func 'mu4e--default-handler (defvar mu4e-header-func 'mu4e~default-handler
"A function called for each message returned from the server "A function called for each message returned from the server
process; the function is passed a msg plist as argument. See process; the function is passed a msg plist as argument. See
`mu4e-proc-filter' for the format.") `mu4e~proc-filter' for the format.")
(defvar mu4e-found-func 'mu4e--default-handler (defvar mu4e-found-func 'mu4e~default-handler
"A function called for when we received a :found sexp after the "A function called for when we received a :found sexp after the
headers have returns, to report on the number of matches. See headers have returns, to report on the number of matches. See
`mu4e-proc-filter' for the format.") `mu4e~proc-filter' for the format.")
(defvar mu4e-erase-func 'mu4e--default-handler (defvar mu4e-erase-func 'mu4e~default-handler
"A function called for when we received an :erase sexp after the "A function called for when we received an :erase sexp after the
headers have returns, to clear the current headers buffer. See headers have returns, to clear the current headers buffer. See
`mu4e-proc-filter' for the format.") `mu4e~proc-filter' for the format.")
(defvar mu4e-compose-func 'mu4e--default-handler (defvar mu4e-compose-func 'mu4e~default-handler
"A function called for each message returned from the server "A function called for each message returned from the server
process that is used as basis for composing a new message (ie., process that is used as basis for composing a new message (ie.,
either a reply or a forward); the function is passed msg and a either a reply or a forward); the function is passed msg and a
symbol (either reply or forward). See `mu4e-proc-filter' for the symbol (either reply or forward). See `mu4e~proc-filter' for the
format of <msg-plist>.") format of <msg-plist>.")
(defvar mu4e-info-func 'mu4e--default-handler (defvar mu4e-info-func 'mu4e~default-handler
"A function called for each (:info type ....) sexp received from "A function called for each (:info type ....) sexp received from
the server process.") the server process.")
(defvar mu4e-pong-func 'mu4e--default-handler (defvar mu4e-pong-func 'mu4e~default-handler
"A function called for each (:pong type ....) sexp received from "A function called for each (:pong type ....) sexp received from
the server process.") the server process.")
(defvar mu4e-temp-func 'mu4e--default-handler (defvar mu4e-temp-func 'mu4e~default-handler
"A function called for each (:temp <file> <cookie>) sexp received "A function called for each (:temp <file> <cookie>) sexp received
from the server process.") from the server process.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -29,19 +29,23 @@
(require 'mu4e-utils) ;; utility functions (require 'mu4e-utils) ;; utility functions
(require 'mu4e-vars) (require 'mu4e-vars)
(require 'mu4e-mark) (require 'mu4e-mark)
(require 'mu4e-proc)
;; we prefer the improved fill-region ;; we prefer the improved fill-region
(require 'filladapt nil 'noerror) (require 'filladapt nil 'noerror)
(require 'comint) (require 'comint)
;; some buffer-local variables ;; some buffer-local variables
(defvar mu4e--view-hdrs-buffer nil (defvar mu4e~view-hdrs-buffer nil
"*internal* Headers buffer connected to this view.") "*internal* Headers buffer connected to this view.")
(defvar mu4e~view-lines-wrapped nil "*internal* Whether lines are wrapped.")
(defvar mu4e~view-cited-hidden nil "*internal* Whether cited lines are hidden.")
(defun mu4e-view-message-with-msgid (msgid) (defun mu4e-view-message-with-msgid (msgid)
"View message with MSGID. This is meant for external programs "View message with MSGID. This is meant for external programs
wanting to show specific messages - for example, `mu4e-org'." wanting to show specific messages - for example, `mu4e-org'."
(mu4e-proc-view msgid)) (mu4e~proc-view msgid))
(defun mu4e-view-message-text (msg) (defun mu4e-view-message-text (msg)
"Return the message to display (as a string), based on the MSG "Return the message to display (as a string), based on the MSG
@ -52,16 +56,16 @@ plist."
(let ((fieldname (cdr (assoc field mu4e-header-names))) (let ((fieldname (cdr (assoc field mu4e-header-names)))
(fieldval (plist-get msg field))) (fieldval (plist-get msg field)))
(case field (case field
(:subject (mu4e-view-header fieldname fieldval)) (:subject (mu4e~view-construct-header fieldname fieldval))
(:path (mu4e-view-header fieldname fieldval)) (:path (mu4e~view-construct-header fieldname fieldval))
(:maildir (mu4e-view-header fieldname fieldval)) (:maildir (mu4e~view-construct-header fieldname fieldval))
(:flags (mu4e-view-header fieldname (:flags (mu4e~view-construct-header fieldname
(if fieldval (format "%S" fieldval) ""))) (if fieldval (format "%S" fieldval) "")))
;; contact fields ;; contact fields
(:to (mu4e-view-contacts msg field)) (:to (mu4e~view-construct-contacts msg field))
(:from (mu4e-view-contacts msg field)) (:from (mu4e~view-construct-contacts msg field))
(:cc (mu4e-view-contacts msg field)) (:cc (mu4e~view-construct-contacts msg field))
(:bcc (mu4e-view-contacts msg field)) (:bcc (mu4e~view-construct-contacts msg field))
;; if we (`user-mail-address' are the From, show To, otherwise, ;; if we (`user-mail-address' are the From, show To, otherwise,
;; show From ;; show From
@ -69,21 +73,21 @@ plist."
(let* ((from (plist-get msg :from)) (let* ((from (plist-get msg :from))
(from (and from (cdar from)))) (from (and from (cdar from))))
(if (and from (string-match mu4e-user-mail-address-regexp from)) (if (and from (string-match mu4e-user-mail-address-regexp from))
(mu4e-view-contacts msg :to) (mu4e~view-construct-contacts msg :to)
(mu4e-view-contacts msg :from)))) (mu4e~view-construct-contacts msg :from))))
;; date ;; date
(:date (:date
(let ((datestr (let ((datestr
(when fieldval (format-time-string mu4e-view-date-format (when fieldval (format-time-string mu4e-view-date-format
fieldval)))) fieldval))))
(if datestr (mu4e-view-header fieldname datestr) ""))) (if datestr (mu4e~view-construct-header fieldname datestr) "")))
;; size ;; size
(:size (:size
(let* (size (mu4e-view-size msg) (let* (size (mu4e-view-size msg)
(sizestr (when size (format "%d bytes" size)))) (sizestr (when size (format "%d bytes" size))))
(if sizestr (mu4e-view-header fieldname sizestr)))) (if sizestr (mu4e~view-construct-header fieldname sizestr))))
;; attachments ;; attachments
(:attachments (mu4e-view-attachments msg)) (:attachments (mu4e~view-construct-attachments msg))
(t (error "Unsupported field: %S" field))))) (t (error "Unsupported field: %S" field)))))
mu4e-view-fields "") mu4e-view-fields "")
"\n" "\n"
@ -95,8 +99,8 @@ plist."
'In sync' here means that moving to the next/previous message in 'In sync' here means that moving to the next/previous message in
the the message view affects HDRSBUF, as does marking etc. If the the message view affects HDRSBUF, as does marking etc. If
UPDATE is nil, the current message may be (visually) 'massaged', UPDATE is nil, the current message may be (visually) 'massaged',
based on the settings of `mu4e-view-wrap-lines' and based on the settings of `mu4e~view-wrap-lines' and
`mu4e-view-hide-cited'. `mu4e~view-hide-cited'.
As a side-effect, a message that is being viewed loses its 'unread' As a side-effect, a message that is being viewed loses its 'unread'
marking if it still had that." marking if it still had that."
@ -112,30 +116,30 @@ marking if it still had that."
(setq ;; these are buffer-local (setq ;; these are buffer-local
buffer-read-only t buffer-read-only t
mu4e-current-msg msg mu4e-current-msg msg
mu4e--view-hdrs-buffer hdrsbuf mu4e~view-hdrs-buffer hdrsbuf
mu4e-link-map (make-hash-table :size 32 :rehash-size 2 :weakness nil)) mu4e~view-link-map (make-hash-table :size 32 :rehash-size 2 :weakness nil))
(switch-to-buffer buf) (switch-to-buffer buf)
(goto-char (point-min)) (goto-char (point-min))
(mu4e-color-cited) (mu4e~view-fontify-cited)
(mu4e-mark-footer) (mu4e~view-fontify-footer)
(mu4e-make-urls-clickable) (mu4e~view-make-urls-clickable)
(unless update (unless update
;; if we're showing the message for the first time, use the values of ;; if we're showing the message for the first time, use the values of
;; user-settable variables `mu4e-view-wrap-lines' and ;; user-settable variables `mu4e~view-wrap-lines' and
;; `mu4e-view-hide-cited' to determine whether we should wrap/hide ;; `mu4e~view-hide-cited' to determine whether we should wrap/hide
(progn (progn
(when mu4e-view-wrap-lines (mu4e-view-wrap-lines)) (when mu4e~view-lines-wrapped (mu4e~view-wrap-lines))
(when mu4e-view-hide-cited (mu4e-view-hide-cited)))) (when mu4e~view-cited-hidden (mu4e~view-hide-cited))))
;; no use in trying to set flags again ;; no use in trying to set flags again
(unless update (unless update
(mu4e-view-mark-as-read-maybe))))) (mu4e~view-mark-as-read-maybe)))))
(defun mu4e-view-header (key val &optional dont-propertize-val) (defun mu4e~view-construct-header (key val &optional dont-propertize-val)
"Return header KEY with value VAL if VAL is non-nil. If "Return header KEY with value VAL if VAL is non-nil. If
DONT-PROPERTIZE-VAL is non-nil, do not add text-properties to VAL." DONT-PROPERTIZE-VAL is non-nil, do not add text-properties to VAL."
(if val (if val
@ -155,7 +159,7 @@ DONT-PROPERTIZE-VAL is non-nil, do not add text-properties to VAL."
"")) ""))
(defun mu4e-view-contacts (msg field) (defun mu4e~view-construct-contacts (msg field)
"Add a header for a contact field (ie., :to, :from, :cc, :bcc)." "Add a header for a contact field (ie., :to, :from, :cc, :bcc)."
(let* ((lst (plist-get msg field)) (let* ((lst (plist-get msg field))
(fieldname (cdr (assoc field mu4e-header-names))) (fieldname (cdr (assoc field mu4e-header-names)))
@ -173,11 +177,11 @@ DONT-PROPERTIZE-VAL is non-nil, do not add text-properties to VAL."
'help-echo email))) 'help-echo email)))
lst ", ")))) lst ", "))))
(if contacts (if contacts
(mu4e-view-header fieldname contacts) (mu4e~view-construct-header fieldname contacts)
""))) "")))
(defun mu4e-open-save-attach-func (msg attachnum is-open) (defun mu4e~view-open-save-attach-func (msg attachnum is-open)
"Return a function that offers to save attachment NUM. If IS-OPEN "Return a function that offers to save attachment NUM. If IS-OPEN
is nil, and otherwise open it." is nil, and otherwise open it."
(lexical-let ((msg msg) (attachnum attachnum) (is-open is-open)) (lexical-let ((msg msg) (attachnum attachnum) (is-open is-open))
@ -189,7 +193,7 @@ is nil, and otherwise open it."
;; note -- attachments have an index which is needed for the backend, which does ;; note -- attachments have an index which is needed for the backend, which does
;; not necessarily follow 1,2,3,4 etc. ;; not necessarily follow 1,2,3,4 etc.
(defun mu4e-view-attachments (msg) (defun mu4e~view-construct-attachments (msg)
"Display attachment information; the field looks like something like: "Display attachment information; the field looks like something like:
:attachments ((:index 4 :name \"test123.doc\" :attachments ((:index 4 :name \"test123.doc\"
:mime-type \"application/msword\" :size 1234))." :mime-type \"application/msword\" :size 1234))."
@ -202,11 +206,11 @@ is nil, and otherwise open it."
(size (plist-get att :size)) (size (plist-get att :size))
(map (make-sparse-keymap))) (map (make-sparse-keymap)))
(incf id) (incf id)
(define-key map [mouse-2] (mu4e-open-save-attach-func msg id nil)) (define-key map [mouse-2] (mu4e~view-open-save-attach-func msg id nil))
(define-key map [?\r] (mu4e-open-save-attach-func msg id nil)) (define-key map [?\r] (mu4e~view-open-save-attach-func msg id nil))
(define-key map [S-mouse-2](mu4e-open-save-attach-func msg id t)) (define-key map [S-mouse-2](mu4e~view-open-save-attach-func msg id t))
(define-key map (kbd "<S-return>") (define-key map (kbd "<S-return>")
(mu4e-open-save-attach-func msg id t)) (mu4e~view-open-save-attach-func msg id t))
(concat (concat
(propertize (format "[%d]" id) 'face 'mu4e-view-attach-number-face) (propertize (format "[%d]" id) 'face 'mu4e-view-attach-number-face)
(propertize name 'face 'mu4e-view-link-face (propertize name 'face 'mu4e-view-link-face
@ -214,10 +218,10 @@ is nil, and otherwise open it."
(when (and size (> size 0)) (when (and size (> size 0))
(concat (format "(%s)" (concat (format "(%s)"
(propertize (mu4e-display-size size) (propertize (mu4e-display-size size)
'face 'mu4e-view-header-key-face))))))) 'face 'mu4e-header-key-face)))))))
(plist-get msg :attachments) ", "))) (plist-get msg :attachments) ", ")))
(unless (zerop id) (unless (zerop id)
(mu4e-view-header (format "Attachments(%d)" id) attstr t)))) (mu4e~view-construct-header (format "Attachments(%d)" id) attstr t))))
(defvar mu4e-view-mode-map nil (defvar mu4e-view-mode-map nil
@ -263,11 +267,11 @@ is nil, and otherwise open it."
#'(lambda () (interactive) (scroll-up -1))) #'(lambda () (interactive) (scroll-up -1)))
;; navigation between messages ;; navigation between messages
(define-key map "p" 'mu4e--view-prev-header) (define-key map "p" 'mu4e~view-prev-header)
(define-key map "n" 'mu4e--view-next-header) (define-key map "n" 'mu4e~view-next-header)
;; the same ;; the same
(define-key map (kbd "<M-down>") 'mu4e--view-next-header) (define-key map (kbd "<M-down>") 'mu4e~view-next-header)
(define-key map (kbd "<M-up>") 'mu4e--view-prev-header) (define-key map (kbd "<M-up>") 'mu4e~view-prev-header)
;; switching to view mode (if it's visible) ;; switching to view mode (if it's visible)
(define-key map "y" 'mu4e-select-other-view) (define-key map "y" 'mu4e-select-other-view)
@ -315,7 +319,7 @@ is nil, and otherwise open it."
(define-key menumap [hide-cited] (define-key menumap [hide-cited]
'("Toggle hide cited" . mu4e-view-toggle-hide-cited)) '("Toggle hide cited" . mu4e-view-toggle-hide-cited))
(define-key menumap [raw-view] (define-key menumap [raw-view]
'("View raw message" . mu4e-raw-view)) '("View raw message" . mu4e-view-raw-message))
(define-key menumap [pipe] (define-key menumap [pipe]
'("Pipe through shell" . mu4e-view-pipe)) '("Pipe through shell" . mu4e-view-pipe))
;; (define-key menumap [inspect] ;; (define-key menumap [inspect]
@ -347,27 +351,24 @@ is nil, and otherwise open it."
(define-key menumap [jump] '("Jump to maildir" . mu4e-jump-to-maildir)) (define-key menumap [jump] '("Jump to maildir" . mu4e-jump-to-maildir))
(define-key menumap [sepa4] '("--")) (define-key menumap [sepa4] '("--"))
(define-key menumap [next] '("Next" . mu4e--view-next-header)) (define-key menumap [next] '("Next" . mu4e~view-next-header))
(define-key menumap [previous] '("Previous" . mu4e--view-prev-header))) (define-key menumap [previous] '("Previous" . mu4e~view-prev-header)))
map))) map)))
(fset 'mu4e-view-mode-map mu4e-view-mode-map) (fset 'mu4e-view-mode-map mu4e-view-mode-map)
(defvar mu4e-lines-wrapped nil "*internal* Whether lines are wrapped.")
(defvar mu4e-cited-hidden nil "*internal* Whether cited lines are hidden.")
(define-derived-mode mu4e-view-mode special-mode "mu4e:view" (define-derived-mode mu4e-view-mode special-mode "mu4e:view"
"Major mode for viewing an e-mail message in mu4e. "Major mode for viewing an e-mail message in mu4e.
\\{mu4e-view-mode-map}." \\{mu4e-view-mode-map}."
(use-local-map mu4e-view-mode-map) (use-local-map mu4e-view-mode-map)
(make-local-variable 'mu4e--view-hdrs-buffer) (make-local-variable 'mu4e~view-hdrs-buffer)
(make-local-variable 'mu4e-current-msg) (make-local-variable 'mu4e-current-msg)
(make-local-variable 'mu4e-link-map) (make-local-variable 'mu4e~view-link-map)
(make-local-variable 'mu4e-lines-wrapped) (make-local-variable 'mu4e~view-lines-wrapped)
(make-local-variable 'mu4e-cited-hidden) (make-local-variable 'mu4e~view-cited-hidden)
(setq buffer-undo-list t) ;; don't record undo info (setq buffer-undo-list t) ;; don't record undo info
@ -386,7 +387,7 @@ is nil, and otherwise open it."
;; we mark messages are as read when we leave the message; i.e., when skipping ;; we mark messages are as read when we leave the message; i.e., when skipping
;; to the next/previous one, or leaving the view buffer altogether. ;; to the next/previous one, or leaving the view buffer altogether.
(defun mu4e-view-mark-as-read-maybe () (defun mu4e~view-mark-as-read-maybe ()
"Clear the current message's New/Unread status and set it to "Clear the current message's New/Unread status and set it to
Seen; if the message is not New/Unread, do nothing." Seen; if the message is not New/Unread, do nothing."
(when mu4e-current-msg (when mu4e-current-msg
@ -394,9 +395,9 @@ Seen; if the message is not New/Unread, do nothing."
(docid (plist-get mu4e-current-msg :docid))) (docid (plist-get mu4e-current-msg :docid)))
;; is it a new message? ;; is it a new message?
(when (or (member 'unread flags) (member 'new flags)) (when (or (member 'unread flags) (member 'new flags))
(mu4e-proc-move docid nil "+S-u-N"))))) (mu4e~proc-move docid nil "+S-u-N")))))
(defun mu4e-color-cited () (defun mu4e~view-fontify-cited ()
"Colorize message content based on the citation level." "Colorize message content based on the citation level."
(save-excursion (save-excursion
(let ((more-lines t)) (let ((more-lines t))
@ -426,7 +427,7 @@ Seen; if the message is not New/Unread, do nothing."
;; would lead to an infinite loop ;; would lead to an infinite loop
(not (= (point-max) (line-end-position))))))))) (not (= (point-max) (line-end-position)))))))))
(defun mu4e-mark-footer () (defun mu4e~view-fontify-footer ()
"Give the message footers a distinctive color." "Give the message footers a distinctive color."
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(save-excursion (save-excursion
@ -436,15 +437,15 @@ Seen; if the message is not New/Unread, do nothing."
(when p (when p
(add-text-properties p (point-max) '(face mu4e-footer-face))))))) (add-text-properties p (point-max) '(face mu4e-footer-face)))))))
(defvar mu4e-link-map nil (defvar mu4e~view-link-map nil
"*internal* A map of some number->url so we can jump to url by number.") "*internal* A map of some number->url so we can jump to url by number.")
(defconst mu4e-url-regexp (defconst mu4e~view-url-regexp
"\\(https?://[-+a-zA-Z0-9.?_$%/+&#@!~,:;=/()]+\\)" "\\(https?://[-+a-zA-Z0-9.?_$%/+&#@!~,:;=/()]+\\)"
"*internal* regexp that matches URLs; match-string 1 will contain "*internal* regexp that matches URLs; match-string 1 will contain
the matched URL, if any.") the matched URL, if any.")
(defun mu4e-browse-url-func (url) (defun mu4e~view-browse-url-func (url)
"Return a function that executes `browse-url' with URL." "Return a function that executes `browse-url' with URL."
(lexical-let ((url url)) (lexical-let ((url url))
(lambda () (lambda ()
@ -453,18 +454,18 @@ Seen; if the message is not New/Unread, do nothing."
;; this is fairly simplistic... ;; this is fairly simplistic...
(defun mu4e-make-urls-clickable () (defun mu4e~view-make-urls-clickable ()
"Turn things that look like URLs into clickable things, and "Turn things that look like URLs into clickable things, and
number them so they can be opened using `mu4e-view-go-to-url'." number them so they can be opened using `mu4e-view-go-to-url'."
(let ((num 0)) (let ((num 0))
(save-excursion (save-excursion
(goto-char (point-min)) (goto-char (point-min))
(while (re-search-forward mu4e-url-regexp nil t) (while (re-search-forward mu4e~view-url-regexp nil t)
(let ((url (match-string 0)) (let ((url (match-string 0))
(map (make-sparse-keymap))) (map (make-sparse-keymap)))
(define-key map [mouse-2] (mu4e-browse-url-func url)) (define-key map [mouse-2] (mu4e~view-browse-url-func url))
(define-key map [?\r] (mu4e-browse-url-func url)) (define-key map [?\r] (mu4e~view-browse-url-func url))
(puthash (incf num) url mu4e-link-map) (puthash (incf num) url mu4e~view-link-map)
(add-text-properties 0 (length url) (add-text-properties 0 (length url)
`(face mu4e-view-link-face `(face mu4e-view-link-face
mouse-face highlight mouse-face highlight
@ -474,80 +475,64 @@ number them so they can be opened using `mu4e-view-go-to-url'."
'face 'mu4e-view-url-number-face)))))))) 'face 'mu4e-view-url-number-face))))))))
;; functions for org-contacts
(defun mu4e-view-snarf-from (name-or-email)
"Get the From:-data for the current message; NAME-OR-EMAIL should
be a symbol 'name or 'email to get the corresponding field. If the
field is not found, \"\" is returned.
You can use this with e.g. org-contact with a template like: (defun mu4e~view-wrap-lines ()
(\"c\" \"Contacts\" entry (file \"~/Org/contacts.org\")
\"* %(mu4e-view-snarf-from 'name)
:PROPERTIES:
:EMAIL: %(mu4e-view-snarf-from 'email)
:END:\")))
See the `org-contacts' documentation for more details."
;; FIXME: we need to explictly go to some view buffer, since when using this
;; from org-capture, we'll be taken to the capture buffer instead.
(with-current-buffer mu4e-view-buffer-name
(unless (eq major-mode 'mu4e-view-mode)
(error "Not in mu4e-view mode."))
(unless mu4e-current-msg
(error "No current message."))
(let ((from (car-safe (plist-get mu4e-current-msg :from))))
(cond
((not from) "") ;; nothing found
((eq name-or-email 'name)
(or (car-safe from) ""))
((eq name-or-email 'email)
(or (cdr-safe from) ""))
(t (error "Not supported: %S" name-or-email))))))
(defun mu4e-view-wrap-lines ()
"Wrap lines in the message body." "Wrap lines in the message body."
(save-excursion (save-excursion
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(goto-char (point-min)) (goto-char (point-min))
(when (search-forward "\n\n") ;; search for the message body (when (search-forward "\n\n") ;; search for the message body
(fill-region (point) (point-max))) (fill-region (point) (point-max)))
(setq mu4e-lines-wrapped t)))) (setq mu4e~view-lines-wrapped t))))
(defun mu4e-view-hide-cited () (defun mu4e~view-hide-cited ()
"Toggle hiding of cited lines in the message body." "Toggle hiding of cited lines in the message body."
(save-excursion (save-excursion
(let ((inhibit-read-only t)) (let ((inhibit-read-only t))
(goto-char (point-min)) (goto-char (point-min))
(flush-lines "^[:blank:]*>") (flush-lines "^[:blank:]*>")
(setq mu4e-cited-hidden t)))) (setq mu4e~view-cited-hidden t))))
(defun mu4e~view-hdrs-move (lines)
"Move point LINES lines forward (if LINES is positive) or
backward (if LINES is negative). If this succeeds, return the new
docid. Otherwise, return nil."
(when (buffer-live-p mu4e~view-hdrs-buffer)
(with-current-buffer mu4e~view-hdrs-buffer
(mu4e~hdrs-move lines))))
(defun mu4e~view-next-header()(interactive)(mu4e~view-hdrs-move 1))
(defun mu4e~view-prev-header()(interactive)(mu4e~view-hdrs-move -1))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Interactive functions ;; Interactive functions
(defun mu4e-view-toggle-wrap-lines () (defun mu4e-view-toggle-wrap-lines ()
"Toggle line wrap in the message body." "Toggle line wrap in the message body."
(interactive) (interactive)
(if mu4e-lines-wrapped (if mu4e~view-lines-wrapped
(mu4e-view-refresh) (mu4e-view-refresh)
(mu4e-view-wrap-lines))) (mu4e~view-wrap-lines)))
(defun mu4e-view-toggle-hide-cited () (defun mu4e-view-toggle-hide-cited ()
"Toggle hiding of cited lines in the message body." "Toggle hiding of cited lines in the message body."
(interactive) (interactive)
(if mu4e-cited-hidden (if mu4e~view-cited-hidden
(mu4e-view-refresh) (mu4e-view-refresh)
(mu4e-view-hide-cited))) (mu4e~view-hide-cited)))
(defun mu4e-view-refresh () (defun mu4e-view-refresh ()
"Redisplay the current message, without wrapped lines or hidden "Redisplay the current message, without wrapped lines or hidden
citations." citations."
(interactive) (interactive)
(mu4e-view mu4e-current-msg mu4e--view-hdrs-buffer t) (mu4e-view mu4e-current-msg mu4e~view-hdrs-buffer t)
(setq (setq
mu4e-lines-wrapped nil mu4e~view-lines-wrapped nil
mu4e-cited-hidden nil)) mu4e~view-cited-hidden nil))
(defun mu4e-view-kill-buffer-and-window () (defun mu4e-view-kill-buffer-and-window ()
"Quit the message view and return to the headers." "Quit the message view and return to the headers."
@ -558,18 +543,6 @@ citations."
(kill-buffer-and-window) (kill-buffer-and-window)
(kill-buffer))))) (kill-buffer)))))
(defun mu4e--view-hdrs-move (lines)
"Move point LINES lines forward (if LINES is positive) or
backward (if LINES is negative). If this succeeds, return the new
docid. Otherwise, return nil."
(when (buffer-live-p mu4e--view-hdrs-buffer)
(with-current-buffer mu4e--view-hdrs-buffer
(mu4e--hdrs-move lines))))
(defun mu4e--view-next-header()(interactive)(mu4e--view-hdrs-move 1))
(defun mu4e--view-prev-header()(interactive)(mu4e--view-hdrs-move -1))
(defun mu4e-view-action (&optional msg) (defun mu4e-view-action (&optional msg)
"Ask user for some action to apply on MSG (or message-at-point, "Ask user for some action to apply on MSG (or message-at-point,
if nil), then do it. The actions are specified in if nil), then do it. The actions are specified in
@ -582,7 +555,7 @@ if nil), then do it. The actions are specified in
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; attachment handling ;; attachment handling
(defun mu4e--get-attach-num (prompt msg) (defun mu4e~view-get-attach-num (prompt msg)
"Ask the user with PROMPT for an attachment number for MSG, and "Ask the user with PROMPT for an attachment number for MSG, and
ensure it is valid. The number is [1..n] for attachments ensure it is valid. The number is [1..n] for attachments
[0..(n-1)] in the message." [0..(n-1)] in the message."
@ -593,7 +566,7 @@ if nil), then do it. The actions are specified in
(read-number (format "%s (1): " prompt) 1) (read-number (format "%s (1): " prompt) 1)
(read-number (format "%s (1-%d): " prompt count))))) (read-number (format "%s (1-%d): " prompt count)))))
(defun mu4e--get-attach (msg attnum) (defun mu4e~view-get-attach (msg attnum)
"Return the attachment plist in MSG corresponding to attachment "Return the attachment plist in MSG corresponding to attachment
number ATTNUM." number ATTNUM."
(let ((attlist (plist-get msg :attachments))) (let ((attlist (plist-get msg :attachments)))
@ -607,8 +580,8 @@ message-at-point if nil) to disk."
(error "`mu4e-attachment-dir' is not set")) (error "`mu4e-attachment-dir' is not set"))
(let* ((msg (or msg (mu4e-message-at-point))) (let* ((msg (or msg (mu4e-message-at-point)))
(attnum (or attnum (attnum (or attnum
(mu4e--get-attach-num "Attachment to save" msg))) (mu4e~view-get-attach-num "Attachment to save" msg)))
(att (mu4e--get-attach msg attnum)) (att (mu4e~view-get-attach msg attnum))
(path (concat mu4e-attachment-dir "/" (plist-get att :name))) (path (concat mu4e-attachment-dir "/" (plist-get att :name)))
(index (plist-get att :index)) (index (plist-get att :index))
(retry t)) (retry t))
@ -617,7 +590,7 @@ message-at-point if nil) to disk."
(setq retry (setq retry
(and (file-exists-p path) (and (file-exists-p path)
(not (y-or-n-p (concat "Overwrite " path "?")))))) (not (y-or-n-p (concat "Overwrite " path "?"))))))
(mu4e-proc-extract (mu4e~proc-extract
'save (plist-get msg :docid) index path))) 'save (plist-get msg :docid) index path)))
@ -627,42 +600,42 @@ message-at-point if nil)."
(interactive) (interactive)
(let* ((msg (or msg (mu4e-message-at-point))) (let* ((msg (or msg (mu4e-message-at-point)))
(attnum (or attnum (attnum (or attnum
(mu4e--get-attach-num "Attachment to open" msg))) (mu4e~view-get-attach-num "Attachment to open" msg)))
(att (mu4e--get-attach msg attnum)) (att (mu4e~view-get-attach msg attnum))
(index (plist-get att :index))) (index (plist-get att :index)))
(mu4e-proc-extract 'open (plist-get msg :docid) index))) (mu4e~proc-extract 'open (plist-get msg :docid) index)))
(defun mu4e--temp-action (docid index what &optional param) (defun mu4e~temp-action (docid index what &optional param)
"Open attachment INDEX for message with DOCID, and invoke "Open attachment INDEX for message with DOCID, and invoke
ACTION." ACTION."
(interactive) (interactive)
(mu4e-proc-extract 'temp docid index nil what param)) (mu4e~proc-extract 'temp docid index nil what param))
(defun mu4e-view-open-attachment-with (msg attachnum &optional cmd) (defun mu4e-view-open-attachment-with (msg attachnum &optional cmd)
"Open MSG's attachment ATTACHNUM with CMD; if CMD is nil, ask "Open MSG's attachment ATTACHNUM with CMD; if CMD is nil, ask
user for it." user for it."
(interactive) (interactive)
(let* ((att (mu4e--get-attach msg attachnum)) (let* ((att (mu4e~view-get-attach msg attachnum))
(cmd (or cmd (read-string "Shell command to open it with: "))) (cmd (or cmd (read-string "Shell command to open it with: ")))
(index (plist-get att :index))) (index (plist-get att :index)))
(mu4e--temp-action (plist-get msg :docid) index "open-with" cmd))) (mu4e~temp-action (plist-get msg :docid) index "open-with" cmd)))
(defun mu4e-view-pipe-attachment (msg attachnum &optional pipecmd) (defun mu4e-view-pipe-attachment (msg attachnum &optional pipecmd)
"Feed MSG's attachment ATTACHNUM throught pipe PIPECMD; if "Feed MSG's attachment ATTACHNUM throught pipe PIPECMD; if
PIPECMD is nil, ask user for it." PIPECMD is nil, ask user for it."
(interactive) (interactive)
(let* ((att (mu4e--get-attach msg attachnum)) (let* ((att (mu4e~view-get-attach msg attachnum))
(pipecmd (or pipecmd (read-string "Pipe: "))) (pipecmd (or pipecmd (read-string "Pipe: ")))
(index (plist-get att :index))) (index (plist-get att :index)))
(mu4e--temp-action (plist-get msg :docid) index "pipe" pipecmd))) (mu4e~temp-action (plist-get msg :docid) index "pipe" pipecmd)))
(defun mu4e-view-open-attachment-emacs (msg attachnum) (defun mu4e-view-open-attachment-emacs (msg attachnum)
"Open MSG's attachment ATTACHNUM in the current emacs instance." "Open MSG's attachment ATTACHNUM in the current emacs instance."
(interactive) (interactive)
(let* ((att (mu4e--get-attach msg attachnum)) (let* ((att (mu4e~view-get-attach msg attachnum))
(index (plist-get att :index))) (index (plist-get att :index)))
(mu4e--temp-action (plist-get msg :docid) index "emacs"))) (mu4e~temp-action (plist-get msg :docid) index "emacs")))
(defun mu4e-view-attachment-action (&optional msg) (defun mu4e-view-attachment-action (&optional msg)
@ -674,7 +647,7 @@ message-at-point, then do it. The actions are specified in
(actionfunc (mu4e-choose-action (actionfunc (mu4e-choose-action
"Action on attachment: " "Action on attachment: "
mu4e-view-attachment-actions)) mu4e-view-attachment-actions))
(attnum (mu4e--get-attach-num "Which attachment" msg))) (attnum (mu4e~view-get-attach-num "Which attachment" msg)))
(when (and actionfunc attnum) (when (and actionfunc attnum)
(funcall actionfunc msg attnum)))) (funcall actionfunc msg attnum))))
@ -683,7 +656,7 @@ message-at-point, then do it. The actions are specified in
;; want to do something with one of the attachments. ;; want to do something with one of the attachments.
(defun mu4e-view-temp-handler (path what param) (defun mu4e-view-temp-handler (path what param)
"Handler function for doing things with temp files (ie., "Handler function for doing things with temp files (ie.,
attachments) in response to a (mu4e-proc-extract 'temp ... )." attachments) in response to a (mu4e~proc-extract 'temp ... )."
(cond (cond
((string= what "open-with") ((string= what "open-with")
;; 'param' will be the program to open-with ;; 'param' will be the program to open-with
@ -701,21 +674,18 @@ attachments) in response to a (mu4e-proc-extract 'temp ... )."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; marking ;;; marking
(defun mu4e--view-mark-set (mark) (defun mu4e~view-mark-set (mark)
"Set mark on the current messages." "Set mark on the current messages."
(unless (buffer-live-p mu4e--view-hdrs-buffer) (unless (buffer-live-p mu4e~view-hdrs-buffer)
(error "No headers buffer available")) (error "No headers buffer available"))
(let ((docid (mu4e-msg-field mu4e-current-msg :docid))) (let ((docid (mu4e-msg-field mu4e-current-msg :docid)))
(with-current-buffer mu4e--view-hdrs-buffer (with-current-buffer mu4e~view-hdrs-buffer
(if (eq mark 'move) (if (eq mark 'move)
(mu4e-mark-for-move-set) (mu4e-mark-for-move-set)
(mu4e-mark-at-point mark))))) (mu4e-mark-at-point mark)))))
;; (when (not (eq mark 'unmark))
;; (mu4e--view-next-header)
;; (mu4e-view-message)))))
(defun mu4e--split-view-p () (defun mu4e~split-view-p ()
"Return t if we're in split-view, nil otherwise." "Return t if we're in split-view, nil otherwise."
(member mu4e-split-view '(horizontal vertical))) (member mu4e-split-view '(horizontal vertical)))
@ -723,7 +693,7 @@ attachments) in response to a (mu4e-proc-extract 'temp ... )."
"If we're in split-view, unmark all messages. Otherwise, warn "If we're in split-view, unmark all messages. Otherwise, warn
user that unmarking only works in the header list." user that unmarking only works in the header list."
(interactive) (interactive)
(if (mu4e--split-view-p) (if (mu4e~split-view-p)
(mu4e-mark-unmark-all) (mu4e-mark-unmark-all)
(message "Unmarking needs to be done in the header list view"))) (message "Unmarking needs to be done in the header list view")))
@ -731,52 +701,52 @@ user that unmarking only works in the header list."
"If we're in split-view, unmark message at point. Otherwise, warn "If we're in split-view, unmark message at point. Otherwise, warn
user that unmarking only works in the header list." user that unmarking only works in the header list."
(interactive) (interactive)
(if (mu4e--split-view-p) (if (mu4e~split-view-p)
(mu4e--view-mark-set 'unmark) (mu4e~view-mark-set 'unmark)
(message "Unmarking needs to be done in the header list view"))) (message "Unmarking needs to be done in the header list view")))
(defun mu4e-view-mark-for-move () (defun mu4e-view-mark-for-move ()
"Mark the current message for moving." "Mark the current message for moving."
(interactive) (interactive)
(mu4e--view-mark-set 'move) (mu4e~view-mark-set 'move)
(mu4e--view-next-header)) (mu4e~view-next-header))
(defun mu4e-view-mark-for-trash () (defun mu4e-view-mark-for-trash ()
"Mark the current message for moving to the trash folder." "Mark the current message for moving to the trash folder."
(interactive) (interactive)
(mu4e--view-mark-set 'trash) (mu4e~view-mark-set 'trash)
(mu4e--view-next-header)) (mu4e~view-next-header))
(defun mu4e-view-mark-for-delete () (defun mu4e-view-mark-for-delete ()
"Mark the current message for deletion." "Mark the current message for deletion."
(interactive) (interactive)
(mu4e--view-mark-set 'delete) (mu4e~view-mark-set 'delete)
(mu4e--view-next-header)) (mu4e~view-next-header))
(defun mu4e-view-marked-execute () (defun mu4e-view-marked-execute ()
"If we're in split-view, execute the marks. Otherwise, warn user "If we're in split-view, execute the marks. Otherwise, warn user
that execution can only take place in n the header list." that execution can only take place in n the header list."
(interactive) (interactive)
(if (mu4e--split-view-p) (if (mu4e~split-view-p)
(with-current-buffer mu4e--view-hdrs-buffer (with-current-buffer mu4e~view-hdrs-buffer
(mu4e-mark-execute-all)) (mu4e-mark-execute-all))
(message "Execution needs to be done in the header list view"))) (message "Execution needs to be done in the header list view")))
(defun mu4e-view-go-to-url (num) (defun mu4e-view-go-to-url (num)
"Go to a numbered url." "Go to a numbered url."
(interactive "nGo to url with number: ") (interactive "nGo to url with number: ")
(let ((url (gethash num mu4e-link-map))) (let ((url (gethash num mu4e~view-link-map)))
(unless url (error "Invalid number for URL")) (unless url (error "Invalid number for URL"))
(browse-url url))) (browse-url url)))
(defconst mu4e-view-raw-buffer-name "*mu4e-raw-view*" (defconst mu4e~view-raw-buffer-name "*mu4e-raw-view*"
"*internal* Name for the raw message view buffer") "*internal* Name for the raw message view buffer")
(defun mu4e-view-raw-message () (defun mu4e-view-raw-message ()
"Display the raw contents of message at point in a new buffer." "Display the raw contents of message at point in a new buffer."
(interactive) (interactive)
(let ((path (mu4e-field-at-point :path)) (let ((path (mu4e-field-at-point :path))
(buf (get-buffer-create mu4e-view-raw-buffer-name))) (buf (get-buffer-create mu4e~view-raw-buffer-name)))
(unless (and path (file-readable-p path)) (unless (and path (file-readable-p path))
(error "Not a readable file: %S" path)) (error "Not a readable file: %S" path))
(with-current-buffer buf (with-current-buffer buf
@ -788,8 +758,8 @@ that execution can only take place in n the header list."
(switch-to-buffer buf))) (switch-to-buffer buf)))
(defun mu4e-view-pipe (cmd) (defun mu4e-view-pipe (cmd)
"Pipe the message through shell command CMD, and display the "Pipe the message at point through shell command CMD, and display
results." the results."
(interactive "sShell command: ") (interactive "sShell command: ")
(let ((path (mu4e-field-at-point :path))) (let ((path (mu4e-field-at-point :path)))
(mu4e-process-file-through-pipe path cmd))) (mu4e-process-file-through-pipe path cmd)))

View File

@ -45,12 +45,12 @@
;; ;;
;; ;;
;; these are all defined in mu4e-hdrs ;; these are all defined in mu4e-hdrs
(setq mu4e-update-func 'mu4e-hdrs-update-handler) (setq mu4e-update-func 'mu4e~hdrs-update-handler)
(setq mu4e-header-func 'mu4e-hdrs-header-handler) (setq mu4e-header-func 'mu4e~hdrs-header-handler)
(setq mu4e-found-func 'mu4e-hdrs-found-handler) (setq mu4e-found-func 'mu4e~hdrs-found-handler)
(setq mu4e-view-func 'mu4e-hdrs-view-handler) (setq mu4e-view-func 'mu4e~hdrs-view-handler)
(setq mu4e-remove-func 'mu4e-hdrs-remove-handler) (setq mu4e-remove-func 'mu4e~hdrs-remove-handler)
(setq mu4e-erase-func 'mu4e-hdrs-clear) (setq mu4e-erase-func 'mu4e~hdrs-clear)
;; these ones are define in mu4e-utils ;; these ones are define in mu4e-utils
(setq mu4e-info-func 'mu4e-info-handler) (setq mu4e-info-func 'mu4e-info-handler)
@ -59,13 +59,13 @@
;; registers mu4e-pong func ;; registers mu4e-pong func
;; this one is defined in mu4e-compose ;; this one is defined in mu4e-compose
(setq mu4e-compose-func 'mu4e-compose-handler) (setq mu4e-compose-func 'mu4e~compose-handler)
;; note: mu4e-compose.el dynamically registers mu4e-sent-func ;; note: mu4e-compose.el dynamically registers mu4e-sent-func
;; we don't do that here, because it's only a local (temporary) ;; we don't do that here, because it's only a local (temporary)
;; handler ;; handler
;; this one is defined in mu4e-view ;; this one is defined in mu4e-view
(setq mu4e-temp-func 'mu4e-view-temp-handler) (setq mu4e-temp-func 'mu4e~view-temp-handler)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;