diff --git a/emacs/mu4e-compose.el b/emacs/mu4e-compose.el index 51e64841..bbc1d2c4 100644 --- a/emacs/mu4e-compose.el +++ b/emacs/mu4e-compose.el @@ -268,9 +268,9 @@ are more than 1 (based on ORIGMSG)." ?a ;; with one recipient, we can reply to 'all'.... (mu4e-read-option "Reply to " - `( (,(format "all %d recipients" recipnum)) - ("sender only")))))) - (= response ?a))) + `( (,(format "all %d recipients" recipnum) . 'all) + ("sender only" . 'sender-only)))))) + (= response 'all))) (defun mu4e~compose-message-filename-construct (&optional flagstr) "Construct a randomized name for a message file with flags FLAGSTR; it looks diff --git a/emacs/mu4e-headers.el b/emacs/mu4e-headers.el index fb939e32..b5220893 100644 --- a/emacs/mu4e-headers.el +++ b/emacs/mu4e-headers.el @@ -77,7 +77,7 @@ vertical split-view." :group 'mu4e-headers) (defvar mu4e-headers-actions - '( ("capture message" ?c mu4e-action-capture-message)) + '( ("capture message" . mu4e-action-capture-message)) "List of actions to perform on messages in the headers list. The actions are of the form: (NAME SHORTCUT FUNC) where: @@ -117,12 +117,12 @@ are of the form: "The view window connected to this headers view.") (defvar mu4e~headers-sortfield-choices - '( ("date" nil date) - ("from" nil from) - ("prio" nil prio) - ("size" ?z size) - ("subject" nil subject) - ("to" nil to)) + '( ("date" . date) + ("from" . from) + ("prio" . prio) + ("zsize" . size) + ("subject" . subject) + ("to" . to)) "List of cells describing the various sort-options (in the format needed for `mu4e-read-option'.") @@ -644,9 +644,10 @@ non-nill, don't raise an error when the docid is not found." last query, sorting settings." (let* ((cell (find-if (lambda (cell) - (eq (nth 2 cell) mu4e-headers-sortfield)) + (eq (cdr cell) mu4e-headers-sortfield)) mu4e~headers-sortfield-choices)) - (optchar (or (nth 1 cell) (substring (nth 0 cell) 0 1)))) + (optchar (substring (car cell) 0 1))) + (message "==> %S" optchar) (setq global-mode-string (concat (propertize mu4e~headers-last-query 'face 'mu4e-title-face) @@ -723,14 +724,14 @@ header." "Ask user for a mark; return (MARK . TARGET)." (let* ((mark (mu4e-read-option "Mark to set: " - '( ("move" nil move) - ("trash" ?d trash) - ("elete" ?D delete) - ("unread" ?o unread) - ("read" nil read) - ("flag" ?+ flag) - ("unflag" ?- unflag) - ("unmark" nil unmark)))) + '( ("move" . move) + ("dtrash" . trash) + ("Delete" . delete) + ("ounread" . unread) + ("read" . read) + ("+flag" . flag) + ("-unflag" . unflag) + ("unmark" . unmark)))) (target (when (eq mark 'move) (mu4e-ask-maildir-check-exists "Move message to: ")))) @@ -746,9 +747,9 @@ matching messages with that mark." (interactive) (let ((markpair (mu4e~headers-get-markpair)) (field (mu4e-read-option "Field to match: " - '(("subject" nil :subject) - ("from" nil :from) - ("to" nil :to)))) + '( ("subject" . :subject) + ("from" . :from) + ("to" . :to)))) (pattern (read-string (mu4e-format "Regexp:") nil 'mu4e~headers-regexp-hist))) @@ -934,7 +935,7 @@ rerun the last search with the new parameters." (mu4e-read-option "Sortfield: " mu4e~headers-sortfield-choices)) (revert (mu4e-read-option "Direction: " - '(("ascending" nil nil) ("descending" nil t))))) + '(("ascending" . nil) ("descending" . t))))) (setq mu4e-headers-sortfield sortfield mu4e-headers-sort-revert revert) diff --git a/emacs/mu4e-mark.el b/emacs/mu4e-mark.el index c7f23883..6faf3008 100644 --- a/emacs/mu4e-mark.el +++ b/emacs/mu4e-mark.el @@ -240,8 +240,8 @@ action', return nil means 'don't do anything'" (setq what (let ((what (mu4e-read-option "There are existing marks; should we: " - '( ("apply marks" nil apply) - ("ignore marks?" nil ignore))))) + '( ("apply marks" . apply) + ("ignore marks?" . ignore))))) ;; we determined what to do... now do it (when (eq what 'apply) (mu4e-mark-execute-all t)))))))) diff --git a/emacs/mu4e-utils.el b/emacs/mu4e-utils.el index ae5f1485..a2524864 100644 --- a/emacs/mu4e-utils.el +++ b/emacs/mu4e-utils.el @@ -69,26 +69,7 @@ dir already existed, or has been created, nil otherwise." "Like `message', but prefixed with mu4e." (message "%s" (apply 'mu4e-format frm args))) - -(defun mu4e~read-option-normalize-list (options) - "Turn a list OPTIONS into normal-form for `mu4e-read-option'." - ;; transform options into 'normal-form', so that in case an option has 'nil - ;; for CHAR, it's replaced by the first letter of OPTIONSTRING (and that char - ;; is eaten off OPTIONSTR. If RESULT is nil, replace it by CHAR - (map 'list - (lambda (option) - (if (nth 1 option) - (list - (nth 0 option) - (nth 1 option) - (or (nth 2 option) (nth 1 option))) ; - (list - (substring (nth 0 option) 1) ;; chop off first char - (string-to-char (nth 0 option)) ;; first char as shortcut - (or (nth 2 option) (nth 1 option) - (string-to-char (nth 0 option)))))) - options)) - + (defun mu4e~read-char-choice (prompt choices) "Compatiblity wrapper for `read-char-choice', which is emacs-24 only." @@ -105,47 +86,45 @@ describes a multiple-choice question to the user, OPTIONS describe the options, and is a list of cells describing particular options. Cells have the following structure: - (OPTIONSTRING CHAR [RESULT]) - - where CHAR is a short-cut character for the -option, and OPTIONSTRING is a non-empty string describing the -option. If CHAR is nil or not-specified, the first character of the -optionstring is used. - -If RESULT is provide, this will be returned if the user presses the -corresponding CHAR; otherwise, CHAR is returned. + (OPTIONSTRING . RESULT) + where OPTIONSTRING is a non-empty string describing the + option. The first character of OPTIONSTRING is used as the + shortcut, and obviously all shortcuts must be different, so you + can prefix the string with an uniquifying character. + The options are provided as a list for the user to choose from; user can then choose by typing CHAR. Example: (mu4e-read-option \"Choose an animal: \" '((\"Monkey\" ?m) (\"Gnu\" ?g) (\"platipus\"))) User now will be presented with a list: - \"Choose an animal: [m]Monkey, [g]Gnu, [p]latipus\"." - (let* ((options (mu4e~read-option-normalize-list options)) - (prompt (mu4e-format "%s" prompt)) + \"Choose an animal: [m]Monkey, [g]Gnu, [p]latipus\"." + (let* ((prompt (mu4e-format "%s" prompt)) (chosen) (optionsstr (mapconcat (lambda (option) - (let* ((descr (car option)) - (kar (and (cdr option) (cadr option)))) - ;; handle the empty kar case - (unless kar - (setq ;; eat first kar from descr; use it as kar - kar (string-to-char descr) - descr (substring descr 1))) - (concat - "[" (propertize (make-string 1 kar) - 'face 'mu4e-highlight-face) "]" - descr))) options ", ")) + (when (consp (cdr option)) + (error (concat "Please use the new format for options/actions; " + "see the manual"))) + (let* ((kar (substring (car option) 0 1)) + (val (cdr option))) + (concat + "[" (propertize kar 'face 'mu4e-highlight-face) "]" + (substring (car option) 1)))) + options ", ")) (response (mu4e~read-char-choice (concat prompt optionsstr " [" (propertize "C-g" 'face 'mu4e-highlight-face) " to quit]") - (map 'list (lambda(elm) (nth 1 elm)) options))) ;; the allowable chars + ;; the allowable chars + (map 'list (lambda(elm) (string-to-char (car elm))) options))) (chosen - (find-if (lambda (option) (eq response (nth 1 option))) options))) - (nth 2 chosen))) + (find-if + (lambda (option) (eq response (string-to-char (car option)))) + options))) + (unless chosen (error "%S not found" response)) + (cdr chosen))) (defun mu4e~get-maildirs-1 (path &optional mdir) diff --git a/emacs/mu4e-view.el b/emacs/mu4e-view.el index 574a055e..4126d62a 100644 --- a/emacs/mu4e-view.el +++ b/emacs/mu4e-view.el @@ -99,8 +99,8 @@ buffer." :group 'mu4e-view) (defvar mu4e-view-actions - '( ("capture message" ?c mu4e-action-capture-message) - ("view as pdf" ?p mu4e-action-view-as-pdf)) + '( ("capture message" . mu4e-action-capture-message) + ("view as pdf" . mu4e-action-view-as-pdf)) "List of actions to perform on messages in view mode. The actions are of the form: (NAME SHORTCUT FUNC) @@ -110,9 +110,9 @@ where: * FUNC is a function which receives a message plist as an argument.") (defvar mu4e-view-attachment-actions - '( ("open-with" ?w mu4e-view-open-attachment-with) - ("in-emacs" ?e mu4e-view-open-attachment-emacs) - ("pipe" ?| mu4e-view-pipe-attachment)) + '( ("wopen-with" . mu4e-view-open-attachment-with) + ("ein-emacs" . mu4e-view-open-attachment-emacs) + ("|pipe" . mu4e-view-pipe-attachment)) "List of actions to perform on message attachments. The actions are of the form: (NAME SHORTCUT FUNC) diff --git a/emacs/mu4e.texi b/emacs/mu4e.texi index 9ebd5a3f..609ed10b 100644 --- a/emacs/mu4e.texi +++ b/emacs/mu4e.texi @@ -1280,6 +1280,13 @@ You can invoke the actions with @key{a} for actions on messages, and @key{A} for actions on attachments. In the following, we'll gives some examples of defining actions. +Note, the format of the actions has changed slightly since version 0.9.8.4; +@t{mu4e} warns you if you use the old format still. The older format was: +@code{(DESCRIPTION SHORTCUT [VALUE])}, while the new format is a cons-cell, +@code{(DESCRIPTION . VALUE)}; see below for some examples. If your shortcut is +not also the first character of the description, simply prefix the description +with that character. + @subsection Functions for actions Defining a new custom action means that you need to write an elisp-function to @@ -1316,24 +1323,27 @@ Suppose we would like to inspect the number of recipients for a message in the (message "Number of recipients: %d" (+ (length (mu4e-msg-field msg :to)) (length (mu4e-msg-field msg :cc))))) +;; define 'N' (the first letter of the description) as the shortcut (add-to-list 'mu4e-headers-actions - '("Number of recipients" ?n show-number-of-recipients) t) + '("Number of recipients" . show-number-of-recipients) t) @end lisp After activating this, @key{a n} in the headers view will show the number of -recipients for the message at point. +recipients for the message at point. @subsection Example: adding an action in the message view As another example, suppose we would like to search for messages by the sender of this message. + @lisp (defun search-for-sender (msg) "Search for messages sent by the sender of the current one." (mu4e-headers-search (concat "from:" (cdar (mu4e-msg-field msg :from))))) +;; define 'x' as the shortcut (add-to-list 'mu4e-view-actions - '("search for sender" ?x search-for-sender) t) + '("xsearch for sender" . search-for-sender) t) @end lisp @subsection Example: adding an attachment action @@ -1342,14 +1352,15 @@ Finally, let's define an action for an attachment. As mentioned, attachment-action function take @emph{2} arguments, the message and the attachment number to use. -The following will count the number of lines in an attachment. +The following will count the number of lines in an attachment, and define +@key{n} as the shortcut key (the 'n' is prefixed to the description). @lisp (defun count-lines-in-attachment (msg attachnum) "Count the number of lines in an attachment." (mu4e-view-pipe-attachment msg attachnum "wc -l")) (add-to-list 'mu4e-view-attachment-actions - '("count lines" ?n count-lines-in-attachment) t) + '("ncount lines" . count-lines-in-attachment) t) @end lisp @subsection What functions are available?