* mu4e: add tooltips for header fields in message, headers view

This commit is contained in:
djcb 2012-07-10 11:51:54 +03:00
parent 706a686134
commit 129b5ad264
4 changed files with 137 additions and 116 deletions

View File

@ -54,7 +54,7 @@
respective widths in characters. A width of `nil' means respective widths in characters. A width of `nil' means
'unrestricted', and this is best reserved fo the rightmost (last) 'unrestricted', and this is best reserved fo the rightmost (last)
field. For the complete list of available headers, see field. For the complete list of available headers, see
`mu4e-header-names'" `mu4e-header-info'."
:type (list 'symbol) :type (list 'symbol)
:group 'mu4e-headers) :group 'mu4e-headers)
@ -528,17 +528,21 @@ after the end of the search results."
(cons (cons
(make-string (make-string
(+ mu4e~mark-fringe-len (floor (fringe-columns 'left t))) ?\s) (+ mu4e~mark-fringe-len (floor (fringe-columns 'left t))) ?\s)
(map 'list (mapcar
(lambda (item) (lambda (item)
(let ((field (cdr (assoc (car item) mu4e-header-names))) (let* ((info (cadr (assoc (car item) mu4e-header-info)))
(width (cdr item))) (name (plist-get info :shortname))
(help (plist-get info :help))
(width (cdr item)))
(message "%S %S" item info)
(concat (concat
(propertize (propertize
(if width (if width
(truncate-string-to-width field width 0 ?\s t) (truncate-string-to-width name width 0 ?\s t)
field) name)
'face 'mu4e-header-title-face) " "))) 'face 'mu4e-header-title-face
mu4e-headers-fields)))) 'help-echo help) " ")))
mu4e-headers-fields))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; higlighting ;;; higlighting

View File

@ -455,7 +455,7 @@ there is no message at point."
msg))) msg)))
(defun mu4e-field-at-point (field) (defun mu4e-field-at-point (field)
"Get FIELD (a symbol, see `mu4e-header-names') for the message at "Get FIELD (a symbol, see `mu4e-header-info') for the message at
point in eiter the headers buffer or the view buffer." point in eiter the headers buffer or the view buffer."
(plist-get (mu4e-message-at-point t) field)) (plist-get (mu4e-message-at-point t) field))
@ -635,8 +635,9 @@ FUNC (if non-nil) afterwards."
doccount (if (= doccount 1) "" "s"))))) doccount (if (= doccount 1) "" "s")))))
;; send the ping ;; send the ping
(mu4e~proc-ping) (mu4e~proc-ping)
;; get the address list ;; get the address list if it's not already set.
(when mu4e-compose-complete-addresses (when (and mu4e-compose-complete-addresses
(not mu4e~contacts-for-completion))
(setq mu4e-contacts-func 'mu4e~fill-contacts) (setq mu4e-contacts-func 'mu4e~fill-contacts)
(mu4e~proc-contacts (mu4e~proc-contacts
mu4e-compose-complete-only-personal mu4e-compose-complete-only-personal
@ -651,7 +652,8 @@ FUNC (if non-nil) afterwards."
(cancel-timer mu4e-update-timer) (cancel-timer mu4e-update-timer)
(setq (setq
mu4e-update-timer nil mu4e-update-timer nil
mu4e~maildir-list nil)) mu4e~maildir-list nil
mu4e~contacts-for-completion nil))
(mu4e~proc-kill) (mu4e~proc-kill)
;; kill all main/view/headers buffer ;; kill all main/view/headers buffer
(mapcar (mapcar
@ -661,7 +663,6 @@ FUNC (if non-nil) afterwards."
(kill-buffer)))) (kill-buffer))))
(buffer-list))) (buffer-list)))
(defvar mu4e-update-timer nil (defvar mu4e-update-timer nil
"*internal* The mu4e update timer.") "*internal* The mu4e update timer.")

View File

@ -150,14 +150,13 @@ the address fields (this excludes mailing list messages)."
:type 'string :type 'string
:group 'mu4e-compose) :group 'mu4e-compose)
(defcustom mu4e-compose-complete-ignore-address-regexp "noreply" (defcustom mu4e-compose-complete-ignore-address-regexp "no-?reply"
"Ignore any e-mail addresses for completion if they match this "Ignore any e-mail addresses for completion if they match this
regexp." regexp."
:type 'string :type 'string
:group 'mu4e-compose) :group 'mu4e-compose)
;; Folders ;; Folders
(defgroup mu4e-folders nil (defgroup mu4e-folders nil
"Special folders." "Special folders."
@ -331,8 +330,6 @@ flag set)."
:group 'mu4e-faces) :group 'mu4e-faces)
(defface mu4e-system-face (defface mu4e-system-face
'((t :inherit font-lock-comment-face :slant italic)) '((t :inherit font-lock-comment-face :slant italic))
"Face for system message (such as the footers for message "Face for system message (such as the footers for message
@ -342,27 +339,7 @@ headers)."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; internal variables / constants ;; internal variables / constants
(defconst mu4e-header-names
'( (:attachments . "Attach")
(:bcc . "Bcc")
(:cc . "Cc")
(:date . "Date")
(:flags . "Flags")
(:from . "From")
(:from-or-to . "From/To")
(:maildir . "Maildir")
(:path . "Path")
(:subject . "Subject")
(:to . "To"))
"An alist of all possible header fields; this is used in the UI (the
column headers in the header list, and the fields the message
view). Most fields should be self-explanatory. A special one is
`:from-or-to', which is equal to `:from' unless `:from' matches
`mu4e-user-mail-address-regexp', in which case it will be equal to
`:to'.")
(defconst mu4e-logo (defconst mu4e-logo
(propertize "mu4e" 'face 'mu4e-title-face) (propertize "mu4e" 'face 'mu4e-title-face)
"A propertized string for the mu4e 'logo'.") "A propertized string for the mu4e 'logo'.")
@ -370,30 +347,69 @@ view). Most fields should be self-explanatory. A special one is
(defconst mu4e-prefix (defconst mu4e-prefix
(concat "[" mu4e-logo "]") (concat "[" mu4e-logo "]")
"Prefix for mu4e minibuffer input.") "Prefix for mu4e minibuffer input.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defconst mu4e-header-info
;; internal variables / constants '( (:attachments .
( :name "Attachments"
(defconst mu4e-header-names :shortname "Atts"
'( (:attachments . "Attach") :help "Message attachments"))
(:bcc . "Bcc") (:bcc .
(:cc . "Cc") ( :name "Bcc"
(:date . "Date") :shortname "Bcc"
(:flags . "Flags") :help "Blind Carbon-Copy recipients for the message"
(:from . "From") :sortable t))
(:from-or-to . "From/To") (:cc
(:maildir . "Maildir") ( :name "Cc"
(:path . "Path") :shortname "Cc"
(:subject . "Subject") :help "Carbon-Copy recipients for the message"
(:to . "To")) :sortable t))
"An alist of all possible header fields; this is used in the UI (the (:date
column headers in the header list, and the fields the message ( :name "Date"
view). Most fields should be self-explanatory. A special one is :shortname "Date"
`:from-or-to', which is equal to `:from' unless `:from' matches :help "Date/time when the message was written"
`mu4e-user-mail-address-regexp', in which case it will be equal to :sortable t))
`:to'.") (:flags
( :name "Flags"
:shortname "Flgs"
:help "Flags for the message"
:sortable t))
(:from
( :name "From"
:shortname "From"
:help "The sender of the message"
:sortable t))
(:from-or-to
( :name "From/To"
:shortname "From/To"
:help "Sender of the message if it's not me; otherwise
the recipient"
:sortable t))
(:maildir
( :name "Maildir"
:shortname "Maildir"
:help "Maildir for this message"
:sortable t))
(:path
( :name "Path"
:shortname "Path"
:help "Full filesystem path to the message"
:sortable t))
(:subject
( :name "Subject"
:shortname "S"
:help "Subject of the message"
:sortable t))
(:to
( :name "To"
:shortname "T"
:help "Recipient of the message"
:sortable t)))
"An alist of all possible header fields and information about
them.; this is used in the UI (the column headers in the header
list, and the fields the message view). Most fields should be
self-explanatory. A special one is `:from-or-to', which is equal to
`:from' unless `:from' matches `mu4e-user-mail-address-regexp', in
which case it will be equal to `:to'.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -49,7 +49,7 @@
(defcustom mu4e-view-fields (defcustom mu4e-view-fields
'(:from :to :cc :subject :flags :date :maildir :attachments) '(:from :to :cc :subject :flags :date :maildir :attachments)
"Header fields to display in the message view buffer. For the "Header fields to display in the message view buffer. For the
complete list of available headers, see `mu4e-header-names'." complete list of available headers, see `mu4e-header-info'."
:type (list 'symbol) :type (list 'symbol)
:group 'mu4e-view) :group 'mu4e-view)
@ -104,11 +104,12 @@ buffer."
("view as pdf" . mu4e-action-view-as-pdf)) ("view as pdf" . mu4e-action-view-as-pdf))
"List of actions to perform on messages in view mode. The actions "List of actions to perform on messages in view mode. The actions
are of the form: are of the form:
(NAME SHORTCUT FUNC) (NAME FUNC)
where: where:
* NAME is the name of the action (e.g. \"Count lines\") * NAME is the name of the action (e.g. \"Count lines\")
* SHORTCUT is a one-character shortcut to call this action * FUNC is a function which receives a message plist as an argument.
* FUNC is a function which receives a message plist as an argument.")
The first letter of NAME is used as a shortcut character.")
(defvar mu4e-view-attachment-actions (defvar mu4e-view-attachment-actions
'( ("wopen-with" . mu4e-view-open-attachment-with) '( ("wopen-with" . mu4e-view-open-attachment-with)
@ -116,12 +117,13 @@ where:
("|pipe" . mu4e-view-pipe-attachment)) ("|pipe" . mu4e-view-pipe-attachment))
"List of actions to perform on message attachments. The actions "List of actions to perform on message attachments. The actions
are of the form: are of the form:
(NAME SHORTCUT FUNC) (NAME FUNC)
where: where:
* NAME is the name of the action (e.g. \"Count lines\") * NAME is the name of the action (e.g. \"Count lines\")
* SHORTCUT is a one-character shortcut to call this action * FUNC is a function which receives two arguments: the message
* FUNC is a function which receives two arguments: the message plist and the attachment number.
plist and the attachment number.")
The first letter of NAME is used as a shortcut character.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -157,13 +159,12 @@ plist."
(concat (concat
(mapconcat (mapconcat
(lambda (field) (lambda (field)
(let ((fieldname (cdr (assoc field mu4e-header-names))) (let ((fieldval (plist-get msg field)))
(fieldval (plist-get msg field)))
(case field (case field
(:subject (mu4e~view-construct-header fieldname fieldval)) (:subject (mu4e~view-construct-header field fieldval))
(:path (mu4e~view-construct-header fieldname fieldval)) (:path (mu4e~view-construct-header field fieldval))
(:maildir (mu4e~view-construct-header fieldname fieldval)) (:maildir (mu4e~view-construct-header field fieldval))
(:flags (mu4e~view-construct-header fieldname (:flags (mu4e~view-construct-header field
(if fieldval (format "%S" fieldval) ""))) (if fieldval (format "%S" fieldval) "")))
;; contact fields ;; contact fields
(:to (mu4e~view-construct-contacts msg field)) (:to (mu4e~view-construct-contacts msg field))
@ -184,12 +185,12 @@ plist."
(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-construct-header fieldname datestr) ""))) (if datestr (mu4e~view-construct-header field 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-construct-header fieldname sizestr)))) (if sizestr (mu4e~view-construct-header field sizestr))))
;; attachments ;; attachments
(:attachments (mu4e~view-construct-attachments msg)) (:attachments (mu4e~view-construct-attachments msg))
(t (error "Unsupported field: %S" field))))) (t (error "Unsupported field: %S" field)))))
@ -237,47 +238,46 @@ marking if it still had that."
(mu4e~view-mark-as-read-maybe)))))) (mu4e~view-mark-as-read-maybe))))))
(defun mu4e~view-construct-header (key val &optional dont-propertize-val) (defun mu4e~view-construct-header (field val &optional dont-propertize-val)
"Return header KEY with value VAL if VAL is non-nil. If "Return header field FIELD (as in `mu4e-header-info') with value
DONT-PROPERTIZE-VAL is non-nil, do not add text-properties to VAL." VAL if VAL is non-nil. If DONT-PROPERTIZE-VAL is non-nil, do not
(if val add text-properties to VAL."
(with-temp-buffer (let* ((info (cadr (assoc field mu4e-header-info)))
(insert (propertize key 'face 'mu4e-view-header-key-face) ": " (key (plist-get info :name))
(if dont-propertize-val (help (plist-get info :help)))
val (if (and val (> (length val) 0))
(propertize val 'face 'mu4e-view-header-value-face)) "\n") (with-temp-buffer
;; temporarily set the fill column <margin> positions to the right, so (insert (propertize key
;; we can indent following lines with positions 'face 'mu4e-view-header-key-face
(let*((margin 1) (fill-column (- fill-column margin))) 'help-echo help) ": "
(fill-region (point-min) (point-max)) (if dont-propertize-val
(goto-char (point-min)) val
(while (and (zerop (forward-line 1)) (not (looking-at "^$"))) (propertize val 'face 'mu4e-view-header-value-face)) "\n")
(indent-to-column margin))) ;; temporarily set the fill column <margin> positions to the right, so
(buffer-string)) ;; we can indent following lines with positions
"")) (let*((margin 1) (fill-column (- fill-column margin)))
(fill-region (point-min) (point-max))
(goto-char (point-min))
(while (and (zerop (forward-line 1)) (not (looking-at "^$")))
(indent-to-column margin)))
(buffer-string))
"")))
(defun mu4e~view-construct-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)) (mu4e~view-construct-header field
(fieldname (cdr (assoc field mu4e-header-names))) (mapconcat
(contacts (lambda(c)
(and lst (let ((name (car c)) (email (cdr c)))
(mapconcat (propertize
(lambda(c) (if name
(let ((name (car c)) (email (cdr c))) (if mu4e-view-show-addresses
(propertize (format "%s <%s>" name email)
(if name (format "%s" name))
(if mu4e-view-show-addresses (format "%s" email))
(format "%s <%s>" name email) 'help-echo email)))
(format "%s" name)) (plist-get msg field) ", ")))
(format "%s" email))
'help-echo email)))
lst ", "))))
(if contacts
(mu4e~view-construct-header fieldname contacts)
"")))
(defun mu4e~view-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."