mu4e: contexts: auto select one at startup, document

When contexts have been defined, automatically select one at startup --
either the first whose match-function returns non-nil, or simply the
first one.

Document this, too.
This commit is contained in:
djcb 2015-12-15 18:20:31 +02:00
parent d17c2a7012
commit a1d0071dd0
3 changed files with 76 additions and 33 deletions

View File

@ -87,17 +87,27 @@ for the message replied to or forwarded, and nil otherwise. Before composing a n
(mu4e-message "Switched context to %s" (mu4e-context-name context)) (mu4e-message "Switched context to %s" (mu4e-context-name context))
context)) context))
(defun mu4e-context-determine (msg) (defun mu4e-context-autoselect ()
"When contexts are defined but there is no context yet, switch
to the first whose :match-func return non-nil. If none of them
match, return the first."
(when (and mu4e-contexts (not (mu4e-context-current)))
(mu4e-context-switch
(mu4e-context-name (mu4e-context-determine nil 'pick-first)))))
(defun mu4e-context-determine (msg &optional pick-first)
"Return the first context with a match-func that returns t. MSG "Return the first context with a match-func that returns t. MSG
points to the plist for the message replied to or forwarded, or points to the plist for the message replied to or forwarded, or
nil if there is no such MSG; similar to what nil if there is no such MSG; similar to what
`mu4e-compose-pre-hook' does. If no context matches, return `mu4e-compose-pre-hook' does.
nil."
If there are contexts but none match, return nil, unless
PICK-FIRST is non-nil, in which case return the first context."
(when mu4e-contexts (when mu4e-contexts
(find-if (lambda (context) (or (find-if (lambda (context)
(and (mu4e-context-match-func context) (and (mu4e-context-match-func context)
(funcall (mu4e-context-match-func context) msg))) (funcall (mu4e-context-match-func context) msg))) mu4e-contexts)
mu4e-contexts))) (car mu4e-contexts))))
(provide 'mu4e-context) (provide 'mu4e-context)

View File

@ -46,6 +46,8 @@
(declare-function mu4e~proc-mkdir "mu4e-proc") (declare-function mu4e~proc-mkdir "mu4e-proc")
(declare-function mu4e~proc-running-p "mu4e-proc") (declare-function mu4e~proc-running-p "mu4e-proc")
(declare-function mu4e-context-autoselect "mu4e-context")
(declare-function show-all "org") (declare-function show-all "org")
@ -148,8 +150,6 @@ see its docstring)."
(mu4e-error (mu4e-error "mu4e-attachment-dir evaluates to nil"))))) (mu4e-error (mu4e-error "mu4e-attachment-dir evaluates to nil")))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e~guess-maildir (path) (defun mu4e~guess-maildir (path)
"Guess the maildir for some path, or nil if cannot find it." "Guess the maildir for some path, or nil if cannot find it."
@ -163,8 +163,6 @@ see its docstring)."
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e-create-maildir-maybe (dir) (defun mu4e-create-maildir-maybe (dir)
"Offer to create maildir DIR if it does not exist yet. "Offer to create maildir DIR if it does not exist yet.
@ -722,9 +720,18 @@ list of contacts we use for autocompletion; otherwise, do nothing."
(mu4e-parse-time-string mu4e-compose-complete-only-after))))))) (mu4e-parse-time-string mu4e-compose-complete-only-after)))))))
(defun mu4e~start (&optional func) (defun mu4e~start (&optional func)
"If mu4e is already running, execute function FUNC (if non-nil). "If `mu4e-contexts' have been defined, but we don't have a
context yet, switch to the matching one, or none matches, the
first.
If mu4e is already running, execute function FUNC (if non-nil).
Otherwise, check various requirements, then start mu4e. When Otherwise, check various requirements, then start mu4e. When
successful, call FUNC (if non-nil) afterwards." successful, call FUNC (if non-nil) afterwards."
;; auto-select some account
(mu4e-context-autoselect)
;; (when (and mu4e-contexts (not (mu4e-context-current)))
;; (mu4e-switch-context (mu4e-context-determine nil 'pick-first))
;; if we're already running, simply go to the main view ;; if we're already running, simply go to the main view
(if (mu4e-running-p) ;; already running? (if (mu4e-running-p) ;; already running?
(when func ;; yes! run func if defined (when func ;; yes! run func if defined

View File

@ -2255,13 +2255,14 @@ example:
@menu @menu
* Defining a context:: * Defining a context::
* Default context::
* Contexts example:: * Contexts example::
* Contexts notes:: * Contexts notes::
* Some context tricks::
@end menu @end menu
It can be useful to be able to switch between different sets of settings It can be useful to be able to switch between different sets of settings
in mu4e; typical examples include the case where you have different in @t{mu4e}; typical examples include the case where you have different
e-mail accounts for private and work email, each with their own settings e-mail accounts for private and work email, each with their own settings
for e-mail addresses, mailservers etc. for e-mail addresses, mailservers etc.
@ -2293,6 +2294,11 @@ an optional function that is invoked before replying to or forwarding a
message with the given message plist as parameter, or @t{nil} when message with the given message plist as parameter, or @t{nil} when
composing a brand new message. The function should return @t{t} when composing a brand new message. The function should return @t{t} when
this context is the right one for this message, or @t{nil} otherwise. this context is the right one for this message, or @t{nil} otherwise.
The function is also invoked when starting @t{mu4e} to determine the
starting context; in that case, the message-parameter is nil. You can
use e.g. the host you're running or or perhaps the time of day or even
your location to determine the context.
@item @t{vars}: @item @t{vars}:
an alist of variable settings for this account. an alist of variable settings for this account.
@end itemize @end itemize
@ -2300,18 +2306,29 @@ an alist of variable settings for this account.
@t{mu4e} uses a variable @code{mu4e-contexts}, which is a list of such @t{mu4e} uses a variable @code{mu4e-contexts}, which is a list of such
objects. objects.
@node Default context
@section Default context
When you have defined contexts and you start @t{mu4e}, it automatically
switches to the first context whose @code{match-func} returns
non-nil. If none of them do, it picks the first. So, put your 'default'
context as the first in @code{mu4e-contexts}.
@node Contexts example @node Contexts example
@section Example @section Example
Let's look at an example; we define two contexts, 'Private' and 'Work' Let's look at an example; we define two contexts, 'Private' and 'Work'
for a fictional user Alice Derleth. for a fictional user Alice Derleth.
Note that in this case, we automatically switch to the first context
when starting; see the discussion in the previous section.
@lisp @lisp
(setq mu4e-contexts (setq mu4e-contexts
`( ,(make-mu4e-context `( ,(make-mu4e-context
:name "Private" :name "Private"
:enter-func (lambda () (mu4e-message "Private mail")) :enter-func (lambda () (mu4e-message "Switch to the Private context"))
;; no leave-func ;; leave-func not defined
:match-func (lambda (msg) :match-func (lambda (msg)
(when msg (mu4e-message-contact-field-matches msg :to "aliced@@home.com"))) (when msg (mu4e-message-contact-field-matches msg :to "aliced@@home.com")))
:vars '( ( mail-reply-to . "aliced@@home.com" ) :vars '( ( mail-reply-to . "aliced@@home.com" )
@ -2323,7 +2340,8 @@ for a fictional user Alice Derleth.
"Lauttasaari, Finland\n")))) "Lauttasaari, Finland\n"))))
,(make-mu4e-context ,(make-mu4e-context
:name "Work" :name "Work"
:enter-func (lambda () (message "Work")) :enter-func (lambda () (mu4e-message "Switch to the Work context"))
;; leave-fun not defined
:match-func (lambda (msg) :match-func (lambda (msg)
(when msg (mu4e-message-contact-field-matches msg :to "aderleth@@miskatonic.edu"))) (when msg (mu4e-message-contact-field-matches msg :to "aderleth@@miskatonic.edu")))
:vars '( ( mail-reply-to . "aderleth@@miskatonic.edu" ) :vars '( ( mail-reply-to . "aderleth@@miskatonic.edu" )
@ -2333,10 +2351,31 @@ for a fictional user Alice Derleth.
(concat (concat
"Prof. Alice Derleth\n" "Prof. Alice Derleth\n"
"Miskatonic University, Dept. of Occult Sciences\n")))))) "Miskatonic University, Dept. of Occult Sciences\n"))))))
@end lisp
;; Set default context @node Contexts notes
(mu4e-context-switch "Private") @section Context notes
;; Set mu4e-user-mail-address-list to reflect the contexts' addresses
Couple of notes:
@itemize
@item You can manually switch the focus use @code{M-x mu4e-context-switch}, by default bound to @code{;} in headers, view and main mode. The current focus appears in the mode-line.
@item The function @code{mu4e-context-current} returns the current-context; the current context is also visiable in the mode-line when in headers, view or main mode.
@item You can set any kind of variable; including settings for mail servers etc. However, settings like @code{mu4e-maildir} and @code{mu4e-mu-home} are not changeable after they have been set without quiting @t{mu4e} first.
@item @code{leave-func} (if defined) for the context we are leaving, is invoked before the @code{enter-func} (if defined) of the context we are entering.
@item @code{enter-func} (if defined) is invoked before setting the variables.
@item @code{match-func} (if defined) is invoked just before @code{mu4e-compose-pre-hook}.
@item Finally, be careful to get the quotations right -- backticks, single quotes and commas and note the '.' between variable name and value.
@end itemize
@section Some context tricks
@node Some context tricks
It is possible to automatically fill @code{mu4e-user-address-list} by
concatenating the @code{user-mail-address} fields of all contexts:
@lisp
;; This sets `mu4e-user-mail-address-list' to the concatenation of all `user-mail-address' values
;; for all contexts. If you have other mail addresses as well, you'll need to add those manually.
(setq mu4e-user-mail-address-list (setq mu4e-user-mail-address-list
(delq nil (delq nil
(mapcar (lambda (context) (mapcar (lambda (context)
@ -2345,19 +2384,6 @@ for a fictional user Alice Derleth.
mu4e-contexts))) mu4e-contexts)))
@end lisp @end lisp
@node Contexts notes
@section Notes
Couple of notes:
@itemize
@item You can manually switch the focus use @code{M-x mu4e-context-switch}, by default bound to @code{;} in headers, view and main mode. The current focus shows in the mode-line.
@item The function @code{mu4e-context-current} returns the current-context; the current context is also visiable in the mode-line when in headers, view or main mode.
@item You can set any kind of variable; including settings for mail servers etc. However, settings like @code{mu4e-maildir} and @code{mu4e-mu-home} are not changeable after they have been set without quiting @t{mu4e} firts.
@item @code{leave-func} (if defined) for the context we are leaving, is invoked before the @code{enter-func} (if defined) of the context we are entering.
@item @code{enter-func} (if defined) is invoked before setting the variables.
@item @code{match-func} (if defined) is invoked just before @code{mu4e-compose-pre-hook}.
@item Finally, be careful to get the quotations right -- backticks, single quotes and commas and note the '.' between variable name and value.
@end itemize
@node Dynamic folders @node Dynamic folders