mirror of
https://github.com/djcb/mu.git
synced 2024-06-25 07:28:02 +02:00
* mu4e: add support for custom matcher functions (WIP)
This commit is contained in:
parent
0d913c1a1f
commit
2367ab2d67
|
@ -87,6 +87,26 @@ are of the form:
|
|||
* SHORTCUT is a one-character shortcut to call this action
|
||||
* FUNC is a function which receives a message plist as an argument.")
|
||||
|
||||
(defvar mu4e-headers-custom-markers
|
||||
'(("Older than"
|
||||
(lambda (msg date) (time-less-p (mu4e-msg-field msg :date) date))
|
||||
(lambda () (mu4e-get-time-date "Match messages before: ")))
|
||||
("Newer than"
|
||||
(lambda (msg date) (time-less-p date (mu4e-msg-field msg :date)))
|
||||
(lambda () (mu4e-get-time-date "Match messages after: ")))
|
||||
("Bigger than"
|
||||
(lambda (msg bytes) (> (mu4e-msg-field msg :size) (* 1024 bytes)))
|
||||
(lambda () (read-number "Match messages bigger than (Kbytes): "))))
|
||||
"List of custom markers -- functions to mark message that match
|
||||
some custom function. Each of the list members has the following format:
|
||||
(NAME PREDICATE-FUNC PARAM-FUNC)
|
||||
* NAME is the name of the predicate function, and the first character
|
||||
is the shortcut (so keep those unique).
|
||||
* PREDICATE-FUNC is a function that takes to parameters, MSG and (optionally) PARAM,
|
||||
and should return non-nil when there's a match.
|
||||
* PARAM-FUNC is function that is evaluated once, and its value is then passed to
|
||||
PREDICATE-FUNC as PARAM. This is useful for getting user-input.")
|
||||
|
||||
(defvar mu4e-headers-sortfield 'date
|
||||
"Field to sort the headers by. Field must be a symbol, one of:
|
||||
date, subject, size, prio, from, to.")
|
||||
|
@ -401,7 +421,7 @@ after the end of the search results."
|
|||
(define-key map (kbd "u") 'mu4e~headers-mark-unmark)
|
||||
(define-key map (kbd "+") 'mu4e~headers-mark-flag)
|
||||
(define-key map (kbd "-") 'mu4e~headers-mark-unflag)
|
||||
|
||||
(define-key map (kbd "&") 'mu4e-headers-mark-custom)
|
||||
(define-key map "m" 'mu4e-headers-mark-for-move-and-next)
|
||||
|
||||
(define-key map (kbd "*") 'mu4e~headers-mark-deferred)
|
||||
|
@ -737,6 +757,16 @@ header."
|
|||
(defvar mu4e~headers-regexp-hist nil
|
||||
"History list of regexps used.")
|
||||
|
||||
(defun mu4e~headers-mark-for-each-if (markpair mark-pred &optional param)
|
||||
"Mark all headers for with predicate function MARK-PRED return
|
||||
non-nil with MARKPAIR. MARK-PRED is function that takes two
|
||||
arguments, MSG (the message at point) and PARAM (a user-specified
|
||||
parameter). MARKPAIR is a cell (MARK . TARGET)."
|
||||
(mu4e-headers-for-each
|
||||
(lambda (msg)
|
||||
(when (funcall mark-pred msg param)
|
||||
(mu4e-mark-at-point (car markpair) (cdr markpair))))))
|
||||
|
||||
(defun mu4e-headers-mark-pattern ()
|
||||
"Ask user for a kind of mark (move, delete etc.), a field to
|
||||
match and a regular expression to match with. Then, mark all
|
||||
|
@ -750,8 +780,9 @@ matching messages with that mark."
|
|||
(pattern (read-string
|
||||
(mu4e-format "Regexp:")
|
||||
nil 'mu4e~headers-regexp-hist)))
|
||||
(mu4e-headers-for-each
|
||||
(lambda (msg)
|
||||
(mu4e~headers-mark-for-each-if
|
||||
markpair
|
||||
(lambda (msg param)
|
||||
(let* ((do-mark) (value (mu4e-msg-field msg field)))
|
||||
(setq do-mark
|
||||
(if (member field '(:to :from :cc :bcc :reply-to))
|
||||
|
@ -759,10 +790,16 @@ matching messages with that mark."
|
|||
(let ((name (car contact)) (email (cdr contact)))
|
||||
(or (and name (string-match pattern name))
|
||||
(and email (string-match pattern email))))) value)
|
||||
(string-match pattern (or value ""))))
|
||||
(when do-mark
|
||||
(mu4e-mark-at-point (car markpair) (cdr markpair))))))))
|
||||
(string-match pattern (or value "")))))))))
|
||||
|
||||
(defun mu4e-headers-mark-custom ()
|
||||
"Mark messages based on a user-provided predicate function."
|
||||
(interactive)
|
||||
(let* ((pred (mu4e-read-option "Match function: "
|
||||
mu4e-headers-custom-markers))
|
||||
(param (when (cdr pred) (eval (cdr pred))))
|
||||
(markpair (mu4e~mark-get-markpair "Mark matched messages with: " t)))
|
||||
(mu4e~headers-mark-for-each-if markpair (car pred) param)))
|
||||
|
||||
(defun mu4e~headers-get-thread-info (msg what)
|
||||
"Get WHAT (a symbol, either path or thread-id) for MSG."
|
||||
|
@ -863,8 +900,6 @@ to get it from; it's a symbol, either 'future or 'past."
|
|||
(pop mu4e~headers-query-future))))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
|
||||
;;; interactive functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defvar mu4e~headers-search-hist nil
|
||||
|
@ -1083,7 +1118,6 @@ maildir)."
|
|||
(mu4e-mark-handle-when-leaving)
|
||||
(mu4e-headers-search (concat "\"maildir:" maildir "\""))))
|
||||
|
||||
|
||||
(defun mu4e-headers-split-view-resize (n)
|
||||
"In horizontal split-view, increase the number of lines shown by
|
||||
N; in vertical split-view, increase the number of columns shown by
|
||||
|
|
|
@ -300,4 +300,5 @@ action', return nil means 'don't do anything'"
|
|||
(when (eq what 'apply)
|
||||
(mu4e-mark-execute-all t))))))))
|
||||
|
||||
|
||||
(provide 'mu4e-mark)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
(require 'html2text)
|
||||
(require 'mu4e-vars)
|
||||
(require 'doc-view)
|
||||
(require 'org) ;; for org-parse-time-string
|
||||
|
||||
(defcustom mu4e-html2text-command nil
|
||||
"Shell command that converts HTML from stdin into plain text on
|
||||
|
@ -104,7 +105,8 @@ User now will be presented with a list:
|
|||
(optionsstr
|
||||
(mapconcat
|
||||
(lambda (option)
|
||||
(when (consp (cdr option))
|
||||
;; try to detect old-style options...
|
||||
(when (or (characterp (cdr option)) (null (cdr option)))
|
||||
(error (concat "Please use the new format for options/actions; "
|
||||
"see the manual")))
|
||||
(let* ((kar (substring (car option) 0 1))
|
||||
|
@ -325,8 +327,6 @@ http://cr.yp.to/proto/maildir.html "
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
|
||||
(defun mu4e-display-size (size)
|
||||
"Get a string representation of SIZE (in bytes)."
|
||||
(cond
|
||||
|
@ -807,5 +807,12 @@ displaying it). Do _not_ bury the current buffer, though."
|
|||
(delete-window win)))))) nil t)))
|
||||
|
||||
|
||||
(defun mu4e-get-time-date (prompt)
|
||||
"Determine the emacs time value for the time/date entered by user
|
||||
after PROMPT. Formats are all that are accepted by
|
||||
`parse-time-string'."
|
||||
(let ((timestr (read-string (mu4e-format "%s" prompt))))
|
||||
(apply 'encode-time (org-parse-time-string timestr))))
|
||||
|
||||
(provide 'mu4e-utils)
|
||||
;;; End of mu4e-utils.el
|
||||
|
|
|
@ -423,9 +423,10 @@ is nil, and otherwise open it."
|
|||
|
||||
(define-key map (kbd "<delete>") 'mu4e-view-mark-for-delete)
|
||||
(define-key map (kbd "<deletechar>") 'mu4e-mark-for-delete)
|
||||
(define-key map "D" 'mu4e-view-mark-for-delete)
|
||||
(define-key map "m" 'mu4e-view-mark-for-move)
|
||||
|
||||
(define-key map (kbd "D") 'mu4e-view-mark-for-delete)
|
||||
(define-key map (kbd "m") 'mu4e-view-mark-for-move)
|
||||
(define-key map (kbd "&") 'mu4e-view-mark-custom)
|
||||
|
||||
(define-key map (kbd "+") 'mu4e-view-mark-flag)
|
||||
(define-key map (kbd "-") 'mu4e-view-mark-unflag)
|
||||
|
||||
|
@ -926,6 +927,10 @@ attachments) in response to a (mu4e~proc-extract 'temp ... )."
|
|||
(mu4e-mark-for-move-set)
|
||||
(mu4e-mark-at-point mark)))))
|
||||
|
||||
(defun mu4e-view-mark-custom ()
|
||||
"Run some custom mark function."
|
||||
(mu4e~view-in-headers-context
|
||||
(mu4e-headers-mark-custom)))
|
||||
|
||||
(defun mu4e~split-view-p ()
|
||||
"Return t if we're in split-view, nil otherwise."
|
||||
|
@ -983,8 +988,7 @@ user that unmarking only works in the header list."
|
|||
(mu4e~view-mark-set 'deferred)
|
||||
(mu4e-view-headers-next))
|
||||
|
||||
|
||||
(defun mu4e-view-marked-execute ()
|
||||
(defun mu4e-view-marked-execute ()
|
||||
"Execute the marks."
|
||||
(interactive)
|
||||
(mu4e~view-in-headers-context
|
||||
|
|
|
@ -1235,6 +1235,7 @@ Marking can happen in both the @ref{Headers view} and the @ref{Message view}.
|
|||
* What to mark for::
|
||||
* Executing the marks::
|
||||
* Leaving the headers buffer::
|
||||
* Custom mark functions::
|
||||
* Some marking examples::
|
||||
@end menu
|
||||
|
||||
|
@ -1302,6 +1303,48 @@ When you quit the buffer (for example, but doing a new search) with marks being
|
|||
present, @t{mu4e} asks you what to do with them, depending on the value of the
|
||||
variable @code{mu4e-headers-leave-behavior} -- see its documentation.
|
||||
|
||||
@node Custom mark functions
|
||||
@section Custom mark functions
|
||||
|
||||
Sometimes, the built-in functions to mark messages may not be sufficient for
|
||||
your needs. For this, @t{mu4e} offers an easy way to define your own custom
|
||||
mark functions. You can choose one of the custom marker functions using
|
||||
@key{&} in @ref{Headers view} and @ref{Message view}.
|
||||
|
||||
Custom mark functions should be appended to the list
|
||||
@code{mu4e-headers-custom-markers}. Each of the elements of this list
|
||||
('markers') is a list with three (or two) elements:
|
||||
@itemize
|
||||
@item The name of the marker - as short string describing this marker. The
|
||||
first character of this string will also be its shortcut, so these should be
|
||||
unique.
|
||||
@item a predicate function taking two arguments @t{msg} and @t{param}- first,
|
||||
@t{msg}, which is the message
|
||||
plist (see @ref{The message s-expression}); second is a parameter provided by
|
||||
the third of the marker elements (next item). The predicate function should
|
||||
return non-nil if the messages matches.
|
||||
@item (optionally) a function that is evaluated once, and its result is passed as a
|
||||
parameter to the predicate function. This is useful to ask for user-input.
|
||||
@end itemize
|
||||
|
||||
So, let's look at an example: suppose we want to match all messages that have
|
||||
more than @emph{n} recipients. We could do it like this:
|
||||
|
||||
@lisp
|
||||
(add-to-list 'mu4e-headers-custom-markers
|
||||
'("More than n recipients"
|
||||
(lambda (msg n) (> (+ (length (mu4e-msg-field msg :to))
|
||||
(length (mu4e-msg-field msg :cc))) n))
|
||||
(lambda () (read-number "Match messages with more recipients than: "))) t)
|
||||
@end lisp
|
||||
|
||||
After evaluating this, pressing @key{&} should let you choose the custom
|
||||
marker function, and ask you for the parameters.
|
||||
|
||||
As you can see, it's not very hard to define simple functions to match
|
||||
messages. There are some more examples in the defaults for
|
||||
`mu4e-headers-custom-markers'; see @file{mu4e-headers.el}.
|
||||
|
||||
@node Some marking examples
|
||||
@section Some marking examples
|
||||
|
||||
|
@ -1316,6 +1359,7 @@ press @key{% + s hello RET}. Note, the menu system helps you here; all you
|
|||
need to remember is @key{%} for @code{mu4e-headers-mark-pattern}.
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Actions
|
||||
@chapter Actions
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user