mirror of https://github.com/djcb/mu.git
* mu4e: mu4e-message part 3
This commit is contained in:
parent
97c13d0920
commit
5c2025a12c
|
@ -30,8 +30,10 @@
|
|||
(require 'cl)
|
||||
|
||||
(require 'mu4e-utils)
|
||||
(require 'mu4e-message)
|
||||
(require 'mu4e-meta)
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defun mu4e-action-count-lines (msg)
|
||||
|
@ -39,7 +41,7 @@
|
|||
headers view and message-view."
|
||||
(message "Number of lines: %s"
|
||||
(shell-command-to-string
|
||||
(concat "wc -l < " (shell-quote-argument (plist-get msg :path))))))
|
||||
(concat "wc -l < " (shell-quote-argument (mu4e-message-field msg :path))))))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
@ -58,13 +60,12 @@ view."
|
|||
(let* ((pdf
|
||||
(shell-command-to-string
|
||||
(concat mu4e-msg2pdf " "
|
||||
(shell-quote-argument (mu4e-msg-field msg :path))
|
||||
(shell-quote-argument (mu4e-message-field msg :path))
|
||||
" 2> /dev/null")))
|
||||
(pdf (and pdf (> (length pdf) 5)
|
||||
(substring pdf 0 -1)))) ;; chop \n
|
||||
(unless (and pdf (file-exists-p pdf))
|
||||
(message "==> %S %S" pdf (mu4e-msg-field msg :path))
|
||||
(mu4e-error "Failed to create PDF file"))
|
||||
(mu4e-warn "Failed to create PDF file"))
|
||||
(find-file pdf)))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
@ -75,8 +76,8 @@ view."
|
|||
(defun mu4e-action-view-in-browser (msg)
|
||||
"View the body of the message in a web browser. You can influence
|
||||
the browser to use with the variable `browse-url-generic-program'."
|
||||
(let* ((html (mu4e-msg-field msg :body-html))
|
||||
(txt (mu4e-msg-field msg :body-txt))
|
||||
(let* ((html (mu4e-message-field msg :body-html))
|
||||
(txt (mu4e-message-field msg :body-txt))
|
||||
(tmpfile (format "%s%x.html" temporary-file-directory (random t))))
|
||||
(unless (or html txt)
|
||||
(mu4e-error "No body part for this message"))
|
||||
|
@ -96,10 +97,10 @@ the browser to use with the variable `browse-url-generic-program'."
|
|||
|
||||
(defun mu4e-action-message-to-speech (msg)
|
||||
"Pronounce the message text using `mu4e-text2speech-command'."
|
||||
(unless (mu4e-msg-field msg :body-txt)
|
||||
(mu4e-error "No text body for this message"))
|
||||
(unless (mu4e-message-field msg :body-txt)
|
||||
(mu4e-warn "No text body for this message"))
|
||||
(with-temp-buffer
|
||||
(insert (mu4e-msg-field msg :body-txt))
|
||||
(insert (mu4e-message-field msg :body-txt))
|
||||
(shell-command-on-region (point-min) (point-max)
|
||||
mu4e-text2speech-command)))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -142,7 +143,7 @@ store your org-contacts."
|
|||
(mu4e-error "org-capture is not available."))
|
||||
(unless mu4e-org-contacts-file
|
||||
(mu4e-error "`mu4e-org-contacts-file' is not defined."))
|
||||
(let* ((sender (car-safe (mu4e-msg-field msg :from)))
|
||||
(let* ((sender (car-safe (mu4e-message-field msg :from)))
|
||||
(name (car-safe sender)) (email (cdr-safe sender))
|
||||
(blurb
|
||||
(format
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
(require 'mu4e-vars)
|
||||
(require 'mu4e-proc)
|
||||
(require 'mu4e-actions)
|
||||
(require 'mu4e-message)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Composing / Sending messages
|
||||
|
@ -688,32 +689,33 @@ or replied to, otherwise it is nil."
|
|||
a symbol, one of `reply', `forward', `edit', `new'. All but `new'
|
||||
take the message at point as input. Symbol `edit' is only allowed
|
||||
for draft messages."
|
||||
(let ((msg (mu4e-message-at-point 'noerror)))
|
||||
;; some sanity checks
|
||||
(unless (or msg (eq compose-type 'new))
|
||||
(mu4e-warn "No message at point"))
|
||||
(unless (member compose-type '(reply forward edit new))
|
||||
(mu4e-error "Invalid compose type '%S'" compose-type))
|
||||
(when (and (eq compose-type 'edit)
|
||||
(not (member 'draft (mu4e-message-field msg :flags))))
|
||||
(mu4e-warn "Editing is only allowed for draft messages"))
|
||||
;; run the hooks
|
||||
(mu4e~compose-run-hooks compose-type)
|
||||
|
||||
(unless (member compose-type '(reply forward edit new))
|
||||
(mu4e-error "Invalid compose type '%S'" compose-type))
|
||||
(when (and (eq compose-type 'edit)
|
||||
(not (member 'draft (mu4e-field-at-point :flags))))
|
||||
(mu4e-warn "Editing is only allowed for draft messages"))
|
||||
|
||||
;; run the hooks
|
||||
(mu4e~compose-run-hooks compose-type)
|
||||
|
||||
;; '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*
|
||||
(if (eq compose-type 'new)
|
||||
(mu4e~compose-handler 'new)
|
||||
|
||||
;; otherwise, we need the doc-id
|
||||
(let ((docid (mu4e-field-at-point :docid)))
|
||||
;; if there's a visible view window, select that before starting composing
|
||||
;; a new message, so that one will be replaced by the compose window. The
|
||||
;; 10-or-so line headers buffer is not a good place to write it...
|
||||
;; '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*
|
||||
(if (eq compose-type 'new)
|
||||
(mu4e~compose-handler 'new)
|
||||
;; otherwise, we need the doc-id
|
||||
(let ((docid (mu4e-message-field msg :docid)))
|
||||
;; if there's a visible view window, select that before starting composing
|
||||
;; a new message, so that one will be replaced by the compose window. The
|
||||
;; 10-or-so line headers buffer is not a good place to write it...
|
||||
(let ((viewwin (get-buffer-window mu4e~view-buffer)))
|
||||
(when (window-live-p viewwin)
|
||||
(select-window viewwin)))
|
||||
|
||||
;; talk to the backend
|
||||
(mu4e~proc-compose compose-type docid))))
|
||||
;; talk to the backend
|
||||
(mu4e~proc-compose compose-type docid)))))
|
||||
|
||||
(defun mu4e-compose-reply ()
|
||||
"Compose a reply for the message at point in the headers buffer."
|
||||
|
|
|
@ -706,7 +706,7 @@ docid DOCID, or nil if it cannot be found."
|
|||
with DOCID which must be present in the headers buffer."
|
||||
(save-excursion
|
||||
(when (mu4e~headers-goto-docid docid)
|
||||
(mu4e-message-field (mu4e-message-at-point t) field))))
|
||||
(mu4e-message-field (mu4e-message-at-point) field))))
|
||||
|
||||
;;;; markers mark headers for
|
||||
(defun mu4e~headers-mark (docid mark)
|
||||
|
@ -895,28 +895,27 @@ matching messages with that mark."
|
|||
limited to the message at point and its descendants."
|
||||
;; the tread id is shared by all messages in a thread
|
||||
(interactive "P")
|
||||
(let* ((thread-id (mu4e~headers-get-thread-info
|
||||
(mu4e-message-at-point t) 'thread-id))
|
||||
(path (mu4e~headers-get-thread-info
|
||||
(mu4e-message-at-point t) 'path))
|
||||
(let* ((msg (mu4e-message-at-point))
|
||||
(thread-id (mu4e~headers-get-thread-info msg 'thread-id))
|
||||
(path (mu4e~headers-get-thread-info msg 'path))
|
||||
(markpair
|
||||
(mu4e~mark-get-markpair
|
||||
(if subthread "Mark subthread with: " "Mark whole thread with: ")
|
||||
t))
|
||||
(last-marked-point))
|
||||
(mu4e-headers-for-each
|
||||
(lambda (msg)
|
||||
(let ((my-thread-id (mu4e~headers-get-thread-info msg 'thread-id)))
|
||||
(lambda (mymsg)
|
||||
(let ((my-thread-id (mu4e~headers-get-thread-info mymsg 'thread-id)))
|
||||
(if subthread
|
||||
;; subthread matching; msg's thread path should have path as its
|
||||
;; subthread matching; mymsg's thread path should have path as its
|
||||
;; prefix
|
||||
(when (string-match (concat "^" path)
|
||||
(mu4e~headers-get-thread-info msg 'path))
|
||||
(mu4e~headers-get-thread-info mymsg 'path))
|
||||
(mu4e-mark-at-point (car markpair) (cdr markpair))
|
||||
(setq last-marked-point (point)))
|
||||
;; nope; not looking for the subthread; looking for the whole thread
|
||||
(when (string= thread-id
|
||||
(mu4e~headers-get-thread-info msg 'thread-id))
|
||||
(mu4e~headers-get-thread-info mymsg 'thread-id))
|
||||
(mu4e-mark-at-point (car markpair) (cdr markpair))
|
||||
(setq last-marked-point (point)))))))
|
||||
(when last-marked-point
|
||||
|
@ -1106,7 +1105,7 @@ current window. "
|
|||
(interactive)
|
||||
(unless (eq major-mode 'mu4e-headers-mode)
|
||||
(mu4e-error "Must be in mu4e-headers-mode (%S)" major-mode))
|
||||
(let* ((msg (mu4e-message-at-point t))
|
||||
(let* ((msg (mu4e-message-at-point))
|
||||
(docid (or (mu4e-message-field msg :docid)
|
||||
(mu4e-warn "No message at point")))
|
||||
;; decrypt (or not), based on `mu4e-decryption-policy'.
|
||||
|
@ -1234,7 +1233,7 @@ N. Otherwise, don't do anything."
|
|||
"Ask user what to do with message-at-point, then do it. The
|
||||
actions are specified in `mu4e-headers-actions'."
|
||||
(interactive)
|
||||
(let ((msg (mu4e-message-at-point t))
|
||||
(let ((msg (mu4e-message-at-point))
|
||||
(actionfunc (mu4e-read-option "Action: " mu4e-headers-actions)))
|
||||
(funcall actionfunc msg)))
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
;; Code:
|
||||
(require 'mu4e-proc)
|
||||
(require 'mu4e-utils)
|
||||
(require 'mu4e-message)
|
||||
|
||||
(defcustom mu4e-headers-leave-behavior 'ask
|
||||
"What to do when user leaves the headers view (e.g. quits,
|
||||
|
@ -101,7 +102,8 @@ The following marks are available, and the corresponding props:
|
|||
`deferred' n mark this message for *something* (decided later)
|
||||
`unmark' n unmark this message"
|
||||
(interactive)
|
||||
(let* ((docid (mu4e-field-at-point :docid))
|
||||
(let* ((msg (mu4e-message-at-point))
|
||||
(docid (mu4e-message-field msg :docid))
|
||||
;; get a cell with the mark char and the 'target' 'move' already has a
|
||||
;; target (the target folder) the other ones get a pseudo "target", as
|
||||
;; info for the user.
|
||||
|
@ -174,7 +176,7 @@ headers in the region."
|
|||
the region, for moving to maildir TARGET. If target is not
|
||||
provided, function asks for it."
|
||||
(interactive)
|
||||
(mu4e-field-at-point :docid) ;; will raise an error if there is none
|
||||
(mu4e-message-at-point) ;; raises error if there is none
|
||||
(let* ((target (or target (mu4e-ask-maildir "Move message to: ")))
|
||||
(target (if (string= (substring target 0 1) "/")
|
||||
target
|
||||
|
@ -281,8 +283,7 @@ If NO-CONFIRMATION is non-nil, don't ask user for confirmation."
|
|||
mu4e~mark-map)
|
||||
;; in any case, clear the marks map
|
||||
(mu4e~mark-clear))
|
||||
|
||||
|
||||
|
||||
(defun mu4e-mark-docid-marked-p (docid)
|
||||
"Is the given docid marked?"
|
||||
(when (gethash docid mu4e~mark-map) t))
|
||||
|
|
|
@ -28,10 +28,11 @@
|
|||
(eval-when-compile (byte-compile-disable-warning 'cl-functions))
|
||||
|
||||
(require 'mu4e-vars)
|
||||
(require 'mu4e-utils)
|
||||
|
||||
(require 'cl)
|
||||
(require 'html2text)
|
||||
|
||||
|
||||
|
||||
(defcustom mu4e-html2text-command nil
|
||||
"Shell command that converts HTML from stdin into plain text on
|
||||
|
@ -88,16 +89,15 @@ Some notes on the format:
|
|||
;; after all this documentation, the spectacular implementation
|
||||
(plist-get msg field))
|
||||
|
||||
(defsubst mu4e-message-at-point (&optional raise-err)
|
||||
(defsubst mu4e-message-at-point (&optional noerror)
|
||||
"Get the message s-expression for the message at point in either
|
||||
the headers buffer or the view buffer, or nil if there is no such
|
||||
message. If optional RAISE-ERR is non-nil, raise an error when
|
||||
message. If optional NOERROR is non-nil, do not raise an error when
|
||||
there is no message at point."
|
||||
(let ((msg (or (get-text-property (point) 'msg) mu4e~view-msg)))
|
||||
(if msg
|
||||
msg
|
||||
(when raise-err
|
||||
(mu4e-warn "No message at point")))))
|
||||
(unless noerror (mu4e-warn "No message at point")))))
|
||||
|
||||
|
||||
(defun mu4e-message-for-each (msg field func)
|
||||
|
@ -171,4 +171,17 @@ function prefers the text part, but this can be changed by setting
|
|||
(:index 2 :name \"photo.jpg\" :mime-type \"image/jpeg\" :size 147331)."
|
||||
(plist-get msgpart field))
|
||||
|
||||
|
||||
|
||||
;; backward compatibility ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defalias 'mu4e-msg-field 'mu4e-message-field)
|
||||
(defalias 'mu4e-body-text 'mu4e-message-body-text) ;; backward compatibility
|
||||
|
||||
(defun mu4e-field-at-point (field)
|
||||
"Get FIELD (a symbol, see `mu4e-header-info') for the message at
|
||||
point in eiter the headers buffer or the view buffer."
|
||||
(plist-get (mu4e-message-at-point) field))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
(provide 'mu4e-message)
|
||||
|
|
|
@ -28,19 +28,18 @@
|
|||
(eval-when-compile (byte-compile-disable-warning 'cl-functions))
|
||||
(require 'cl)
|
||||
|
||||
(require 'mu4e-message)
|
||||
(require 'mu4e-vars)
|
||||
(require 'mu4e-about)
|
||||
(require 'doc-view)
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; the following is taken from org.el; we copy it here since we don't want to
|
||||
;; depend on org-mode directly (it causes byte-compilation errors) TODO: a
|
||||
;; cleaner solution....
|
||||
(defconst mu4e~ts-regexp0
|
||||
"\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\( +[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
|
||||
(concat
|
||||
"\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)"
|
||||
"\\( +[^]+0-9>\r\n -]+\\)?\\( +\\([0-9]\\{1,2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)")
|
||||
"Regular expression matching time strings for analysis.
|
||||
This one does not require the space after the date, so it can be
|
||||
used on a string that terminates immediately after the date.")
|
||||
|
@ -90,13 +89,15 @@ user-input, don't show anyhting."
|
|||
|
||||
(defun mu4e-error (frm &rest args)
|
||||
"Create [mu4e]-prefixed error based on format FRM and ARGS. Does
|
||||
a local-exit and does not return."
|
||||
a local-exit and does not return, and raises a
|
||||
debuggable (backtrace) error."
|
||||
(mu4e-log 'error (apply 'mu4e-format frm args))
|
||||
(error "%s" (apply 'mu4e-format frm args)))
|
||||
|
||||
(defun mu4e-warn (frm &rest args)
|
||||
"Create [mu4e]-prefixed warning based on format FRM and
|
||||
ARGS. Does a local-exit and does not return."
|
||||
ARGS. Does a local-exit and does not return. In emacs versions
|
||||
below 24.2, the functions is the same as `mu4e-error'."
|
||||
(mu4e-log 'error (apply 'mu4e-format frm args))
|
||||
(if (fboundp 'user-error)
|
||||
(user-error "%s" (apply 'mu4e-format frm args)) ;; only in emacs-trunk
|
||||
|
@ -239,25 +240,6 @@ and offer to create it if it does not exist yet."
|
|||
mdir))
|
||||
|
||||
|
||||
(defun mu4e-mark-for-move-set (&optional target)
|
||||
"Mark message at point or, if region is active, all messages in
|
||||
the region, for moving to maildir TARGET. If target is not
|
||||
provided, function asks for it."
|
||||
(interactive)
|
||||
(unless (mu4e~headers-docid-at-point)
|
||||
(mu4e-warn "No message at point."))
|
||||
(let* ((target (or target (mu4e-ask-maildir "Move message to: ")))
|
||||
(target (if (string= (substring target 0 1) "/")
|
||||
target
|
||||
(concat "/" target)))
|
||||
(fulltarget (concat mu4e-maildir target)))
|
||||
(when (or (file-directory-p fulltarget)
|
||||
(and (yes-or-no-p
|
||||
(mu4e-format "%s does not exist. Create now?" fulltarget))
|
||||
(mu4e~proc-mkdir fulltarget)))
|
||||
(mu4e-mark-set 'move target))))
|
||||
|
||||
|
||||
(defun mu4e-ask-bookmark (prompt &optional kar)
|
||||
"Ask the user for a bookmark (using PROMPT) as defined in
|
||||
`mu4e-bookmarks', then return the corresponding query."
|
||||
|
@ -361,9 +343,6 @@ http://cr.yp.to/proto/maildir.html "
|
|||
(format "%2.1fK" (/ size 1000.0)))
|
||||
((< size 1000) (format "%d" size))
|
||||
(t (propertize "?" 'face 'mu4e-system-face))))
|
||||
|
||||
|
||||
(defalias 'mu4e-body-text 'mu4e-message-body-text) ;; backward compatibility
|
||||
|
||||
|
||||
(defun mu4e-display-manual ()
|
||||
|
@ -377,13 +356,6 @@ top level if there is none."
|
|||
(t "mu4e"))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defalias 'mu4e-msg-field 'mu4e-message-field) ;; backward compatibility
|
||||
|
||||
(defun mu4e-field-at-point (field)
|
||||
"Get FIELD (a symbol, see `mu4e-header-info') for the message at
|
||||
point in eiter the headers buffer or the view buffer."
|
||||
(plist-get (mu4e-message-at-point t) field))
|
||||
|
||||
(defun mu4e-last-query ()
|
||||
"Get the most recent query or nil if there is none."
|
||||
(when (buffer-live-p mu4e~headers-buffer)
|
||||
|
|
|
@ -782,7 +782,7 @@ current message."
|
|||
`(progn
|
||||
(unless '(buffer-live-p mu4e~view-headers-buffer)
|
||||
(mu4e-error "no headers-buffer connected"))
|
||||
(let* ((msg (mu4e-message-at-point t))
|
||||
(let* ((msg (mu4e-message-at-point))
|
||||
(docid (mu4e-message-field msg :docid)))
|
||||
(unless docid
|
||||
(mu4e-error "message without docid: action is not possible."))
|
||||
|
@ -831,7 +831,7 @@ N (prefix argument), to the Nth previous header."
|
|||
if nil), then do it. The actions are specified in
|
||||
`mu4e-view-actions'."
|
||||
(interactive)
|
||||
(let* ((msg (or msg (mu4e-message-at-point t)))
|
||||
(let* ((msg (or msg (mu4e-message-at-point)))
|
||||
(actionfunc (mu4e-read-option "Action: " mu4e-view-actions)))
|
||||
(funcall actionfunc msg)))
|
||||
|
||||
|
@ -935,7 +935,7 @@ will save attachments 1,3,4,5,6 and 8.
|
|||
Furthermore, there is a shortcut \"a\" which so means all
|
||||
attachments, but as this is the default, you may not need it."
|
||||
(interactive)
|
||||
(let* ((msg (or msg (mu4e-message-at-point t)))
|
||||
(let* ((msg (or msg (mu4e-message-at-point)))
|
||||
(attachstr (mu4e~view-get-attach-num
|
||||
"Attachment number range (or 'a' for 'all')" msg t))
|
||||
(count (hash-table-count mu4e~view-attach-map))
|
||||
|
@ -956,7 +956,7 @@ attachments."
|
|||
"Open attachment number ATTNUM (or ask if nil) from MSG (or
|
||||
message-at-point if nil)."
|
||||
(interactive)
|
||||
(let* ((msg (or msg (mu4e-message-at-point t)))
|
||||
(let* ((msg (or msg (mu4e-message-at-point)))
|
||||
(attnum (or attnum
|
||||
(mu4e~view-get-attach-num "Attachment to open" msg)))
|
||||
(att (or (mu4e~view-get-attach msg attnum)))
|
||||
|
@ -1025,7 +1025,7 @@ PIPECMD is nil, ask user for it."
|
|||
message-at-point, then do it. The actions are specified in
|
||||
`mu4e-view-attachment-actions'."
|
||||
(interactive)
|
||||
(let* ((msg (or msg (mu4e-message-at-point t)))
|
||||
(let* ((msg (or msg (mu4e-message-at-point)))
|
||||
(actionfunc (mu4e-read-option
|
||||
"Action on attachment: "
|
||||
mu4e-view-attachment-actions))
|
||||
|
|
Loading…
Reference in New Issue