mirror of https://github.com/djcb/mu.git
Merge branch 'wip/djcb/modeline'
This commit is contained in:
commit
54dc5cfabe
32
NEWS.org
32
NEWS.org
|
@ -41,10 +41,19 @@
|
|||
manual for details.
|
||||
|
||||
- One change is that ~mu4e-split-view~ can no longer be a function; the new
|
||||
way is to use ~display-buffer-alist~ as explained in the [[info:mu4e:Buffer Display][manual]].
|
||||
way is to use ~display-buffer-alist~ as explained in the [[info:mu4e:Buffer Display][manual]]
|
||||
|
||||
- ~mu4e~ now keeps track of the 'baseline' query results and shows the
|
||||
difference from that in the main view. See the [[info:mu4e#Bookmarks and Maildirs][manual entry]] for details.
|
||||
- ~mu4e~ now keeps track of 'baseline' query results and shows the difference
|
||||
from that in the main view and modeline. See the [[info:mu4e#Bookmarks and Maildirs][manual entry]] for details.
|
||||
|
||||
- Related to that, you can now crown one of your bookmarks in =mu4e-bookmarks=
|
||||
with ~:monitor t~, causing it to be highlighted in the main view and used in
|
||||
the mode-line. See the new [[info:mu4e#Modeline][modeline entry]] in the manual; this uses the new
|
||||
=mu4e-modeline-mode= minor-mode.
|
||||
|
||||
- Bookmark ~:query~ values must be strings now; earlier version half-attempted
|
||||
to allow for functions to works as well, but it didn't work. So now we
|
||||
officially remove this.
|
||||
|
||||
- when moving messages (which includes changing flags), file-flags changes
|
||||
are propagated to duplicates of the messages; that is, e.g. the /Seen/ or
|
||||
|
@ -81,7 +90,7 @@
|
|||
further parameters ~mu~ shows both subcommands and scripts. This is a
|
||||
work-in-progress!
|
||||
|
||||
- The per-(week|day|year|year-month) script have been combined into a
|
||||
- The per-(week|day|year|year-month) scripts have been combined into a
|
||||
~histogram~ script. If you have Guile-support enabled, and have ~gnuplot~
|
||||
installed, you can do e.g.,
|
||||
|
||||
|
@ -92,7 +101,7 @@
|
|||
to get a histogram of such messages. Note, this area is under active
|
||||
developement and will likely change.
|
||||
|
||||
*** building
|
||||
*** building and installation
|
||||
|
||||
- the autotools build (which was deprecated since 1.8) has now been removed.
|
||||
we thank it for its services since 2008. We continue with ~meson~.
|
||||
|
@ -339,8 +348,12 @@
|
|||
out on the maling list.
|
||||
|
||||
|
||||
* Old news
|
||||
:PROPERTIES:
|
||||
:VISIBILITY: folded
|
||||
:END:
|
||||
|
||||
* 1.6 (released, as of July 27 2021)
|
||||
** 1.6 (released, as of July 27 2021)
|
||||
|
||||
NOTE: After upgrading, you need to call ~mu init~, with your prefered parameters
|
||||
before you can use ~mu~ / ~mu4e~. This is because the underlying database-schema
|
||||
|
@ -426,10 +439,7 @@
|
|||
- Switch the context for existing draft messages using
|
||||
~mu4e-compose-context-switch~ or ~C-c C-;~ in ~mu4e-compose-mode~.
|
||||
|
||||
* Old news
|
||||
:PROPERTIES:
|
||||
:VISIBILITY: folded
|
||||
:END:
|
||||
|
||||
** 1.4 (released, as of April 18 2020)
|
||||
|
||||
*** mu
|
||||
|
@ -939,7 +949,7 @@ End of search results
|
|||
- org: improve template keywords
|
||||
- rework URL handling
|
||||
|
||||
** Release 0.9.5
|
||||
** Release 0.9.10
|
||||
|
||||
*** mu
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ struct Server::Private {
|
|||
void move_handler(const Command& cmd);
|
||||
void mkdir_handler(const Command& cmd);
|
||||
void ping_handler(const Command& cmd);
|
||||
void queries_handler(const Command& cmd);
|
||||
void quit_handler(const Command& cmd);
|
||||
void remove_handler(const Command& cmd);
|
||||
void sent_handler(const Command& cmd);
|
||||
|
@ -287,17 +288,20 @@ Server::Private::make_command_map()
|
|||
[&](const auto& params) { mkdir_handler(params); }});
|
||||
cmap.emplace(
|
||||
"ping",
|
||||
CommandInfo{
|
||||
ArgMap{},
|
||||
"ping the mu-server and get server information in the response",
|
||||
[&](const auto& params) { ping_handler(params); }});
|
||||
|
||||
cmap.emplace(
|
||||
"queries",
|
||||
CommandInfo{
|
||||
ArgMap{
|
||||
{":queries",
|
||||
ArgInfo{Type::List, false, "queries for which to get read/unread numbers"}},
|
||||
{":skip-dups",
|
||||
ArgInfo{Type::Symbol,
|
||||
false,
|
||||
"whether to exclude messages with duplicate message-ids"}},
|
||||
},
|
||||
"ping the mu-server and get information in response",
|
||||
[&](const auto& params) { ping_handler(params); }});
|
||||
"get unread/totals information for a list of queries",
|
||||
[&](const auto& params) { queries_handler(params); }});
|
||||
|
||||
cmap.emplace("quit", CommandInfo{{}, "quit the mu server", [&](const auto& params) {
|
||||
quit_handler(params);
|
||||
|
@ -916,9 +920,28 @@ Server::Private::ping_handler(const Command& cmd)
|
|||
const auto storecount{store().size()};
|
||||
if (storecount == (unsigned)-1)
|
||||
throw Error{Error::Code::Store, "failed to read store"};
|
||||
Sexp addrs;
|
||||
for (auto&& addr : store().properties().personal_addresses)
|
||||
addrs.add(addr);
|
||||
|
||||
output_sexp(Sexp()
|
||||
.put_props(":pong", "mu")
|
||||
.put_props(":props",
|
||||
Sexp().put_props(
|
||||
":version", VERSION,
|
||||
":personal-addresses", std::move(addrs),
|
||||
":database-path", store().properties().database_path,
|
||||
":root-maildir", store().properties().root_maildir,
|
||||
":doccount", storecount)));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Server::Private::queries_handler(const Command& cmd)
|
||||
{
|
||||
const auto queries{cmd.string_vec_arg(":queries")
|
||||
.value_or(std::vector<std::string>{})};
|
||||
|
||||
Sexp qresults;
|
||||
for (auto&& q : queries) {
|
||||
const auto count{store_.count_query(q)};
|
||||
|
@ -929,22 +952,10 @@ Server::Private::ping_handler(const Command& cmd)
|
|||
":unread", unread));
|
||||
}
|
||||
|
||||
Sexp addrs;
|
||||
for (auto&& addr : store().properties().personal_addresses)
|
||||
addrs.add(addr);
|
||||
|
||||
auto lst = Sexp().put_props(":pong", "mu");
|
||||
auto proplst = Sexp().put_props(
|
||||
":version", VERSION,
|
||||
":personal-addresses", std::move(addrs),
|
||||
":database-path", store().properties().database_path,
|
||||
":root-maildir", store().properties().root_maildir,
|
||||
":doccount", storecount,
|
||||
":queries", std::move(qresults));
|
||||
|
||||
output_sexp(lst.put_props(":props", std::move(proplst)));
|
||||
output_sexp(Sexp(":queries"_sym, std::move(qresults)));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Server::Private::quit_handler(const Command& cmd)
|
||||
{
|
||||
|
|
|
@ -106,8 +106,7 @@ CommandHandler::invoke(const Command& cmd, bool do_validate) const
|
|||
const auto cmit{cmap_.find(cmd.name())};
|
||||
if (cmit == cmap_.cend())
|
||||
return Err(Error::Code::Command,
|
||||
"unknown command in command '%s'",
|
||||
cmd.to_string().c_str());
|
||||
"unknown command '%s'", cmd.to_string().c_str());
|
||||
|
||||
const auto& cmd_info{cmit->second};
|
||||
if (do_validate) {
|
||||
|
|
|
@ -45,6 +45,7 @@ mu4e_srcs=[
|
|||
'mu4e-main.el',
|
||||
'mu4e-mark.el',
|
||||
'mu4e-message.el',
|
||||
'mu4e-modeline.el',
|
||||
'mu4e-obsolete.el',
|
||||
'mu4e-org.el',
|
||||
'mu4e-search.el',
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mu4e-bookmarks.el -- part of mu4e -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2011-2022 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
@ -24,6 +24,8 @@
|
|||
|
||||
;;; Code:
|
||||
(require 'mu4e-helpers)
|
||||
(require 'mu4e-server)
|
||||
(require 'mu4e-modeline)
|
||||
|
||||
|
||||
;;; Configuration
|
||||
|
@ -50,19 +52,24 @@
|
|||
|
||||
Each of the list elements is a plist with at least:
|
||||
`:name' - the name of the query
|
||||
`:query' - the query expression or function
|
||||
`:key' - the shortcut key.
|
||||
`:query' - the query expression string (not a function)
|
||||
`:key' - the shortcut key (single character)
|
||||
|
||||
Note that the :query parameter can be a function/lambda.
|
||||
|
||||
Optionally, you can add the following: `:hide' - if t, the
|
||||
bookmark is hidden from the main-view and speedbar.
|
||||
`:hide-unread' - do not show the counts of unread/total number of
|
||||
matches for the query in the main-view. This can be useful if a
|
||||
bookmark uses a very slow query.
|
||||
Optionally, you can add the following:
|
||||
|
||||
`:hide-unread' is implied from `:hide'. Furthermore, it is
|
||||
implied when `:query' is a function.
|
||||
- `:favorite' - if t, monitor the results of this query, and make
|
||||
it eligible for showing its status in the emacs modeline. At mose
|
||||
one bookmark should have this set to t (otherwise the _first_
|
||||
bookmark is the implicit favorite)
|
||||
- `:hide' - if t, the bookmark is hidden from the main-view and
|
||||
speedbar.
|
||||
- `:hide-unread' - do not show the counts of
|
||||
unread/total number of matches for the query in the main-view.
|
||||
This can be useful if a bookmark uses a very slow query.
|
||||
|
||||
`:hide-unread' is implied from `:hide'.
|
||||
|
||||
Note: for efficiency, queries used to determine the unread/all
|
||||
counts do not discard duplicate or unreadable messages. Thus, the
|
||||
|
@ -72,7 +79,7 @@ query."
|
|||
:group 'mu4e-bookmarks)
|
||||
|
||||
|
||||
(defun mu4e-ask-bookmark (prompt)
|
||||
(defun mu4e-ask-bookmark (prompt)
|
||||
"Ask the user for a bookmark (using PROMPT) as defined in
|
||||
`mu4e-bookmarks', then return the corresponding query."
|
||||
(unless (mu4e-bookmarks) (mu4e-error "No bookmarks defined"))
|
||||
|
@ -88,23 +95,32 @@ query."
|
|||
(kar (read-char (concat prompt bmarks))))
|
||||
(mu4e-get-bookmark-query kar)))
|
||||
|
||||
|
||||
(defun mu4e--bookmark-query (bm)
|
||||
"Get query string for some bookmark."
|
||||
(when bm
|
||||
(let* ((query (or (plist-get bm :query)
|
||||
(mu4e-warn "No query in %S" bm)))
|
||||
;; queries being functions is deprecated.
|
||||
(query (if (functionp query) (funcall query) query)))
|
||||
;; earlier, we allowed for the queries being fucntions
|
||||
(unless (stringp query)
|
||||
(mu4e-warn "Could not get query string from %s" bm))
|
||||
;; apparently, non-UTF8 queries exist, i.e.,
|
||||
;; with maild dir names.
|
||||
(decode-coding-string query 'utf-8 t))))
|
||||
|
||||
|
||||
(defun mu4e-get-bookmark-query (kar)
|
||||
"Get the corresponding bookmarked query for shortcut KAR.
|
||||
Raise an error if none is found."
|
||||
(let* ((chosen-bm
|
||||
(or (seq-find
|
||||
(lambda (bm)
|
||||
(= kar (plist-get bm :key)))
|
||||
(mu4e-bookmarks))
|
||||
(mu4e-warn "Unknown shortcut '%c'" kar)))
|
||||
(expr (plist-get chosen-bm :query))
|
||||
(expr (if (not (functionp expr)) expr
|
||||
(funcall expr)))
|
||||
(query (eval expr)))
|
||||
(if (stringp query)
|
||||
query
|
||||
(mu4e-warn "Expression must evaluate to query string ('%S')" expr))))
|
||||
|
||||
(let ((chosen-bm
|
||||
(or (seq-find
|
||||
(lambda (bm)
|
||||
(= kar (plist-get bm :key)))
|
||||
(mu4e-bookmarks))
|
||||
(mu4e-warn "Unknown shortcut '%c'" kar))))
|
||||
(mu4e--bookmark-query chosen-bm)))
|
||||
|
||||
(defun mu4e-bookmark-define (query name key)
|
||||
"Define a bookmark for QUERY with NAME and shortcut KEY.
|
||||
|
@ -116,8 +132,8 @@ with KEY."
|
|||
(= (plist-get bm :key) key))
|
||||
(mu4e-bookmarks)))
|
||||
(cl-pushnew `(:name ,name
|
||||
:query ,query
|
||||
:key ,key)
|
||||
:query ,query
|
||||
:key ,key)
|
||||
mu4e-bookmarks :test 'equal))
|
||||
|
||||
(defun mu4e-bookmarks ()
|
||||
|
@ -125,9 +141,159 @@ with KEY."
|
|||
Convert from the old format if needed."
|
||||
(seq-map (lambda (item)
|
||||
(if (and (listp item) (= (length item) 3))
|
||||
`(:name ,(nth 1 item) :query ,(nth 0 item)
|
||||
:key ,(nth 2 item))
|
||||
item)) mu4e-bookmarks))
|
||||
`(:name ,(nth 1 item) :query ,(nth 0 item)
|
||||
:key ,(nth 2 item))
|
||||
item))
|
||||
mu4e-bookmarks))
|
||||
|
||||
(defun mu4e-favorite-bookmark ()
|
||||
"Find the favorite bookmark.
|
||||
The favorit bookmark is the first one that has a non-nil
|
||||
':favorite' property, or the first if there is none."
|
||||
(let ((bookmarks (mu4e-bookmarks)))
|
||||
(or (seq-find (lambda (bm) (plist-get bm :favorite))
|
||||
(mu4e-bookmarks))
|
||||
(car-safe bookmarks))))
|
||||
|
||||
;;; Last & baseline query results for bookmarks.
|
||||
|
||||
(defvar mu4e--baseline nil
|
||||
"Some previous version of the query-results.
|
||||
This is used as the baseline to track updates by comparing it to
|
||||
the latest query-results.")
|
||||
(defvar mu4e--baseline-tstamp nil
|
||||
"Timestamp for when the query-results baseline was updated.")
|
||||
|
||||
(defun mu4e--reset-baseline ()
|
||||
(setq mu4e--baseline (mu4e-server-query-results)
|
||||
mu4e--baseline-tstamp (current-time))
|
||||
(mu4e-last-query-results 'force)) ; for side-effects
|
||||
|
||||
|
||||
(defvar mu4e--last-query-results-cached nil)
|
||||
(defun mu4e-last-query-results(&optional force)
|
||||
"Get the results (counts) of the latest queries.
|
||||
|
||||
Either read form the cache or update them when oudated or FORCE
|
||||
is non-nil.
|
||||
|
||||
The queries are the bookmark / maildir queries that are used to
|
||||
populate the read/unread counts in the main view and modeline.
|
||||
They are refreshed when calling `(mu4e)', i.e., when going to the
|
||||
main view.
|
||||
|
||||
When available, the baseline results are added as well.
|
||||
|
||||
The results are a list of elements of the form
|
||||
(:query \"query string\"
|
||||
:count <total number matching count>
|
||||
:unread <number of unread messages in count>
|
||||
[:favorite t]
|
||||
:baseline ( ;; baseline results
|
||||
:count <total number matching count>
|
||||
:unread <number of unread messages in count>)) The
|
||||
baseline part is optional (see `mu4e-reset-query-results') for
|
||||
more details).
|
||||
|
||||
Uses a cached string unless its nil or FORCE is non-nil."
|
||||
(if (and mu4e--last-query-results-cached (not force))
|
||||
mu4e--last-query-results-cached ;; use cache
|
||||
;; otherwise, recalculate.
|
||||
(let* ((favorite (mu4e-favorite-bookmark))
|
||||
(favorite-query
|
||||
(and favorite (mu4e--bookmark-query favorite))))
|
||||
(setq mu4e--last-query-results-cached ;; walk over the remembered queries
|
||||
;; and augment them with the baseline data and ':favorite' flag, if
|
||||
;; any.
|
||||
(seq-map
|
||||
(lambda (qres)
|
||||
;; note: queries can be _functions_ too; use their
|
||||
;; string value.
|
||||
(let* ((query (mu4e--bookmark-query qres))
|
||||
(bres (seq-find ;; find the corresponding baseline entry
|
||||
(lambda (bq)
|
||||
(string= query (mu4e--bookmark-query bq)))
|
||||
mu4e--baseline)))
|
||||
(when (string= query (or favorite-query ""))
|
||||
(plist-put qres :favorite t))
|
||||
(when bres
|
||||
(plist-put qres :baseline
|
||||
`(:count ,(plist-get bres :count)
|
||||
:unread ,(plist-get bres :unread))))
|
||||
qres)) (mu4e-server-query-results))))))
|
||||
|
||||
(defun mu4e-last-query-result (query)
|
||||
"Get the last result for some QUERY or nil if not found.
|
||||
See `mu4e-last-query-results' for the format."
|
||||
(seq-find
|
||||
(lambda (elm) (string= query (mu4e--bookmark-query elm)))
|
||||
(mu4e-last-query-results)))
|
||||
|
||||
;; for Zero-Inbox afficionados
|
||||
(defvar mu4e-modeline-all-clear '("C:" . "🌀")
|
||||
"No more messages at all for this query.")
|
||||
(defvar mu4e-modeline-all-read '("R:" . "✅")
|
||||
"No unread messages left.")
|
||||
(defvar mu4e-modeline-unread-items '("U:" . "📫")
|
||||
"There are some unread items.")
|
||||
(defvar mu4e-modeline-new-items '("N:" . "🔥")
|
||||
"There are some new items after the baseline.
|
||||
I.e., very new messages.")
|
||||
|
||||
(declare-function mu4e-search-bookmark "mu4e-search")
|
||||
(defun mu4e-jump-to-favorite ()
|
||||
"Jump to to the favorite bookmark, if any."
|
||||
(interactive)
|
||||
(when-let ((fav (mu4e--bookmark-query (mu4e-favorite-bookmark))))
|
||||
(mu4e-search-bookmark fav)))
|
||||
|
||||
(defvar mu4e--bookmarks-modeline-cached nil)
|
||||
|
||||
(defun mu4e--bookmarks-modeline-item ()
|
||||
"Modeline item showing message counts for the favorite bookmark.
|
||||
|
||||
This uses the one special ':favorite' bookmark, and if there is
|
||||
one, creates a propertized string for display in the modeline."
|
||||
(or mu4e--bookmarks-modeline-cached
|
||||
(setq mu4e--bookmarks-modeline-cached
|
||||
(when-let ((fav ;; any results for the favorite bookmark item?
|
||||
(seq-find (lambda (bm) (plist-get bm :favorite))
|
||||
(mu4e-last-query-results))))
|
||||
(let* ((unread (plist-get fav :unread))
|
||||
(count (plist-get fav :count))
|
||||
(baseline (plist-get fav :baseline))
|
||||
(baseline-unread
|
||||
(or (when baseline (plist-get baseline :unread)) unread))
|
||||
(delta (- unread baseline-unread)))
|
||||
(propertize
|
||||
(format "%s%s%s/%s "
|
||||
(funcall (if mu4e-use-fancy-chars 'cdr 'car)
|
||||
(cond
|
||||
((> delta 0) mu4e-modeline-new-items)
|
||||
((> unread 0) mu4e-modeline-unread-items)
|
||||
((> count 0) mu4e-modeline-all-read)
|
||||
(t mu4e-modeline-all-clear)))
|
||||
(propertize (number-to-string unread) 'face 'mu4e-header-key-face)
|
||||
(if (<= delta 0) ""
|
||||
(propertize (format "(%+d)" delta)
|
||||
'face 'mu4e-unread-face))
|
||||
(number-to-string count))
|
||||
'help-echo (format "mu4e query: '%s'" (mu4e--bookmark-query fav))
|
||||
'mouse-face 'mode-line-highlight
|
||||
'keymap '(mode-line keymap
|
||||
(mouse-1 . mu4e-jump-to-favorite)
|
||||
(mouse-2 . mu4e-jump-to-favorite)
|
||||
(mouse-3 . mu4e-jump-to-favorite))))))))
|
||||
|
||||
|
||||
(defun mu4e--modeline-update()
|
||||
"Update the modeline and redisplay if mu4e-modeline-mode is
|
||||
active."
|
||||
(when mu4e-modeline-mode
|
||||
(setq mu4e--bookmarks-modeline-cached nil) ;; force recalculation
|
||||
(force-mode-line-update)))
|
||||
|
||||
|
||||
|
||||
(provide 'mu4e-bookmarks)
|
||||
;;; mu4e-bookmarks.el ends here
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mu4e-context.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2015-2022 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2015-2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
@ -28,6 +28,7 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'mu4e-helpers)
|
||||
(require 'mu4e-modeline)
|
||||
|
||||
|
||||
;;; Configuration
|
||||
|
@ -82,14 +83,6 @@ none."
|
|||
(if ctx (mu4e-context-name ctx) "<none>")))
|
||||
ctx))
|
||||
|
||||
(defun mu4e-context-label ()
|
||||
"Propertized string with the current context name.
|
||||
An empty string \"\" if there is none."
|
||||
(if (mu4e-context-current)
|
||||
(concat "[" (propertize (mu4e-quote-for-modeline
|
||||
(mu4e-context-name (mu4e-context-current)))
|
||||
'face 'mu4e-context-face) "]") ""))
|
||||
|
||||
(cl-defstruct mu4e-context
|
||||
"A mu4e context object with the following members:
|
||||
- `name': the name of the context, eg. \"Work\" or \"Private\".
|
||||
|
@ -153,8 +146,7 @@ non-nil."
|
|||
(setq mu4e--context-current context)
|
||||
|
||||
(run-hooks 'mu4e-context-changed-hook)
|
||||
(mu4e-message "Switched context to %s" (mu4e-context-name context))
|
||||
(force-mode-line-update))
|
||||
(mu4e-message "Switched context to %s" (mu4e-context-name context)))
|
||||
context))
|
||||
|
||||
(defun mu4e--context-autoswitch (&optional msg policy)
|
||||
|
@ -204,13 +196,6 @@ as it is."
|
|||
(mu4e--context-ask-user "Select context: ")))
|
||||
(_ nil))))))
|
||||
|
||||
(defun mu4e-context-in-modeline ()
|
||||
"Display the mu4e-context (if any) in a (buffer-specific)
|
||||
global-mode-line."
|
||||
(add-to-list
|
||||
(make-local-variable 'global-mode-string)
|
||||
'(:eval (mu4e-context-label))))
|
||||
|
||||
(defmacro with-mu4e-context-vars (context &rest body)
|
||||
"Evaluate BODY, with variables let-bound for CONTEXT (if any).
|
||||
`funcall'."
|
||||
|
@ -221,6 +206,14 @@ global-mode-line."
|
|||
(mapcar (lambda(cell) (cdr cell)) vars)
|
||||
(eval ,@body))))
|
||||
|
||||
(defun mu4e--context-modeline-item ()
|
||||
"Propertized string with the current context name.
|
||||
An empty string \"\" if there is none."
|
||||
(if (mu4e-context-current)
|
||||
(concat "[" (propertize (mu4e-quote-for-modeline
|
||||
(mu4e-context-name (mu4e-context-current)))
|
||||
'face 'mu4e-context-face) "] " ) ""))
|
||||
|
||||
(define-minor-mode mu4e-context-minor-mode
|
||||
"Mode for switching the mu4e context."
|
||||
:global nil
|
||||
|
@ -231,7 +224,7 @@ global-mode-line."
|
|||
(define-key map (kbd ";") #'mu4e-context-switch)
|
||||
map)
|
||||
:lighter ""
|
||||
(mu4e-context-in-modeline))
|
||||
(mu4e--modeline-register #'mu4e--context-modeline-item))
|
||||
|
||||
;;;
|
||||
(provide 'mu4e-context)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mu4e-headers.el -- part of mu4e -*- lexical-binding: t; coding:utf-8 -*-
|
||||
|
||||
;; Copyright (C) 2011-2022 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
@ -812,7 +812,7 @@ true, do *not* update the query history stack."
|
|||
(mu4e--search-push-query mu4e--search-last-query 'past)))
|
||||
(setq mu4e--search-last-query rewritten-expr)
|
||||
(setq list-buffers-directory rewritten-expr)
|
||||
(mu4e~headers-update-mode-line))
|
||||
(mu4e--modeline-update))
|
||||
|
||||
;; when the buffer is already visible, select it; otherwise,
|
||||
;; switch to it.
|
||||
|
@ -1178,7 +1178,10 @@ The following specs are supported:
|
|||
(mu4e-context-minor-mode)
|
||||
(mu4e-update-minor-mode)
|
||||
(mu4e-search-minor-mode)
|
||||
(hl-line-mode 1))
|
||||
(hl-line-mode 1)
|
||||
|
||||
(mu4e--modeline-register #'mu4e~headers-modeline-item)
|
||||
(mu4e--modeline-update))
|
||||
|
||||
;;; Highlighting
|
||||
|
||||
|
@ -1244,7 +1247,7 @@ message plist, or nil if not found."
|
|||
|
||||
;;; Queries & searching
|
||||
(defvar mu4e~headers-mode-line-label "")
|
||||
(defun mu4e~headers-update-mode-line ()
|
||||
(defun mu4e~headers-modeline-item ()
|
||||
"Update mode-line settings."
|
||||
(let* ((flagstr
|
||||
(mapconcat
|
||||
|
@ -1258,30 +1261,8 @@ message plist, or nil if not found."
|
|||
(,mu4e-search-skip-duplicates
|
||||
. ,mu4e-headers-skip-duplicates-label)
|
||||
(,mu4e-search-hide-enabled . ,mu4e-headers-hide-label))
|
||||
""))
|
||||
(name "mu4e-headers"))
|
||||
|
||||
(setq mode-name name)
|
||||
(setq mu4e~headers-mode-line-label
|
||||
(concat flagstr " " mu4e--search-last-query))
|
||||
|
||||
(make-local-variable 'global-mode-string)
|
||||
|
||||
(add-to-list 'global-mode-string
|
||||
`(:eval
|
||||
(concat
|
||||
(propertize
|
||||
(mu4e-quote-for-modeline ,mu4e~headers-mode-line-label)
|
||||
'face 'mu4e-modeline-face)
|
||||
" "
|
||||
(if (and mu4e-display-update-status-in-modeline
|
||||
(buffer-live-p mu4e--update-buffer)
|
||||
(process-live-p (get-buffer-process
|
||||
mu4e--update-buffer)))
|
||||
(propertize " (updating)" 'face 'mu4e-modeline-face)
|
||||
""))))))
|
||||
|
||||
|
||||
"")))
|
||||
(concat flagstr " " mu4e--search-last-query)))
|
||||
|
||||
;;; Search-based marking
|
||||
|
||||
|
|
|
@ -65,11 +65,6 @@ You can customize the exact fancy characters used with
|
|||
:type 'boolean
|
||||
:group 'mu4e)
|
||||
|
||||
(defcustom mu4e-display-update-status-in-modeline nil
|
||||
"Non-nil value will display the update status in the modeline."
|
||||
:group 'mu4e
|
||||
:type 'boolean)
|
||||
|
||||
;; maybe move the next ones... but they're convenient
|
||||
;; here because they're needed in multiple buffers.
|
||||
|
||||
|
@ -234,101 +229,6 @@ Function returns the cdr of the list element."
|
|||
(cdr chosen)
|
||||
(mu4e-warn "Unknown shortcut '%c'" response))))
|
||||
|
||||
|
||||
|
||||
;;; Server properties
|
||||
(defvar mu4e--server-props nil
|
||||
"Metadata we receive from the mu4e server.
|
||||
Use `mu4e--update-server-props' to update.")
|
||||
|
||||
;; XXX: we could make these session-persistent
|
||||
|
||||
(defvar mu4e--baseline-query-results nil
|
||||
"Some previous version of the query-results.
|
||||
This is used as the baseline to track updates by comparing it to
|
||||
the latest query-results.")
|
||||
|
||||
(defvar mu4e--baseline-query-results-tstamp nil
|
||||
"Timestamp for when the query-results baseline was updated.")
|
||||
|
||||
(defun mu4e-reset-baseline-query-results ()
|
||||
"Reset the baseline query-results."
|
||||
(interactive)
|
||||
(setq mu4e--baseline-query-results nil
|
||||
mu4e--baseline-query-results-tstamp nil))
|
||||
|
||||
(defun mu4e--update-server-props (props)
|
||||
"Update server props and possibly the baseline query results."
|
||||
(setq mu4e--server-props props)
|
||||
(when-let ((queries (plist-get mu4e--server-props :queries)))
|
||||
(unless mu4e--baseline-query-results
|
||||
(setq mu4e--baseline-query-results queries
|
||||
mu4e--baseline-query-results-tstamp (current-time)))))
|
||||
|
||||
(defun mu4e-server-properties ()
|
||||
"Get the server metadata plist."
|
||||
mu4e--server-props)
|
||||
|
||||
(defun mu4e-root-maildir()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :root-maildir))
|
||||
(mu4e-error "Root maildir unknown; did you start mu4e?")))
|
||||
|
||||
(defun mu4e-database-path()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :database-path))
|
||||
(mu4e-error "Root maildir unknown; did you start mu4e?")))
|
||||
|
||||
(defun mu4e-server-version()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :version))
|
||||
(mu4e-error "Version unknown; did you start mu4e?")))
|
||||
|
||||
(defun mu4e-last-query-results ()
|
||||
"Get the results (counts) of the last cached queries.
|
||||
|
||||
The cached queries are the bookmark / maildir queries that are
|
||||
used to populated the read/unread counts in the main view. They
|
||||
are refreshed when calling `(mu4e)', i.e., when going to the main
|
||||
view.
|
||||
|
||||
When available, the based-line results are added as well.
|
||||
|
||||
The results are a list of elements of the form
|
||||
(:query \"query string\"
|
||||
:count <total number matching count>
|
||||
:unread <number of unread messages in count>
|
||||
:baseline ( ;; baseline results
|
||||
:count <total number matching count>
|
||||
:unread <number of unread messages in count>)) The
|
||||
baseline part is optional (see
|
||||
`mu4e-reset-baseline-query-results') for more details)."
|
||||
(unless mu4e--baseline-query-results
|
||||
(mu4e-reset-baseline-query-results))
|
||||
(seq-map (lambda (qres)
|
||||
(let* ((query (plist-get qres :query))
|
||||
(bres (seq-find ;; find the corresponding baseline entry
|
||||
(lambda (bq) (string= query (plist-get bq :query)))
|
||||
mu4e--baseline-query-results)))
|
||||
(when bres
|
||||
(plist-put qres :baseline
|
||||
`(:count ,(plist-get bres :count)
|
||||
:unread ,(plist-get bres :unread))))
|
||||
qres))
|
||||
(plist-get mu4e--server-props :queries)))
|
||||
|
||||
(defun mu4e-last-query-result (query)
|
||||
"Get the last result for some QUERY or nil if not found.
|
||||
See `mu4e-last-query-results' for the format."
|
||||
(seq-find
|
||||
(lambda (elm) ;;; XXX do we need the decoding?
|
||||
(let ((qstring (decode-coding-string (plist-get elm :query) 'utf-8 t)))
|
||||
(string= query qstring)))
|
||||
(mu4e-last-query-results)))
|
||||
|
||||
|
||||
;;; Logging / debugging
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
;;; mu4e-main.el -- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2011-2022 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
@ -24,9 +24,9 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(require 'smtpmail) ;; the queueing stuff (silence elint)
|
||||
(require 'mu4e-helpers) ;; utility functions
|
||||
(require 'mu4e-context) ;; the context
|
||||
(require 'smtpmail)
|
||||
(require 'mu4e-helpers)
|
||||
(require 'mu4e-context)
|
||||
(require 'mu4e-bookmarks)
|
||||
(require 'mu4e-folders)
|
||||
(require 'mu4e-update)
|
||||
|
@ -58,18 +58,6 @@ the personal addresses."
|
|||
:type 'boolean
|
||||
:group 'mu4e-main)
|
||||
|
||||
(defcustom mu4e-main-hide-baseline-delta nil
|
||||
"Whether to hide the baseline-from-delta from the message counts
|
||||
for bookmarks and maildirs."
|
||||
:type 'boolean
|
||||
:group 'mu4e-main)
|
||||
|
||||
(defcustom mu4e-main-auto-reset-baseline t
|
||||
"Automatically reset the baseline when explicitly (interactively)
|
||||
swiching to the main-view (using the `mu4e' command."
|
||||
:type 'boolean
|
||||
:group 'mu4e-main)
|
||||
|
||||
|
||||
;;; Mode
|
||||
(define-derived-mode mu4e-org-mode org-mode "mu4e:org"
|
||||
|
@ -99,11 +87,11 @@ swiching to the main-view (using the `mu4e' command."
|
|||
(interactive)
|
||||
(mu4e-info (concat mu4e-doc-dir "/NEWS.org")))
|
||||
|
||||
(defun mu4e--main-reset-baseline-query-results ()
|
||||
"Main-view version of `mu4e-reset-baseline-query-results'.
|
||||
(defun mu4e--main-reset-baseline()
|
||||
"Main-view version of `mu4e-reset-query-results'.
|
||||
This version handles updating the current screen as well."
|
||||
(interactive)
|
||||
(mu4e-reset-baseline-query-results)
|
||||
(mu4e--reset-baseline)
|
||||
(revert-buffer))
|
||||
|
||||
(defvar mu4e-main-mode-map
|
||||
|
@ -117,7 +105,7 @@ This version handles updating the current screen as well."
|
|||
(define-key map "f" #'smtpmail-send-queued-mail)
|
||||
;;
|
||||
(define-key map "U" #'mu4e-update-mail-and-index)
|
||||
(define-key map "R" #'mu4e--main-reset-baseline-query-results)
|
||||
(define-key map "R" #'mu4e--main-reset-baseline)
|
||||
(define-key map (kbd "C-S-u") #'mu4e-update-mail-and-index)
|
||||
;; for terminal users
|
||||
(define-key map (kbd "C-c C-u") #'mu4e-update-mail-and-index)
|
||||
|
@ -142,15 +130,16 @@ This version handles updating the current screen as well."
|
|||
(mu4e-context-minor-mode)
|
||||
(mu4e-search-minor-mode)
|
||||
(mu4e-update-minor-mode)
|
||||
(set (make-local-variable 'revert-buffer-function) #'mu4e--main-view-real)
|
||||
(add-hook 'mu4e-index-updated-hook #'mu4e--main-update-after-index))
|
||||
(setq-local revert-buffer-function
|
||||
(lambda (_ignore-auto _noconfirm)
|
||||
(mu4e--main-view 'refresh))))
|
||||
|
||||
(defun mu4e--main-action-str (str &optional func-or-shortcut)
|
||||
"Highlight the first occurrence of [.] in STR.
|
||||
If FUNC-OR-SHORTCUT is non-nil and if it is a function, call it
|
||||
when STR is clicked (using RET or mouse-2); if FUNC-OR-SHORTCUT is
|
||||
a string, execute the corresponding keyboard action when it is
|
||||
clicked."
|
||||
clicked. If HIGHLIGHT is non-nil, hightlight the name."
|
||||
(let ((newstr
|
||||
(replace-regexp-in-string
|
||||
"\\[\\(..?\\)\\]"
|
||||
|
@ -175,8 +164,7 @@ clicked."
|
|||
(if (stringp func-or-shortcut)
|
||||
(length newstr)
|
||||
(- (length newstr) 1))
|
||||
'mouse-face 'highlight newstr)
|
||||
newstr))
|
||||
'mouse-face 'highlight newstr) newstr))
|
||||
|
||||
(defun mu4e--longest-of-maildirs-and-bookmarks ()
|
||||
"Return the length of longest name of bookmarks and maildirs."
|
||||
|
@ -194,7 +182,11 @@ clicked."
|
|||
(used for alignment)."
|
||||
(concat
|
||||
(mu4e--main-action-str
|
||||
(concat "\t* [" fullkey "] " name) fullkey)
|
||||
(format "\t* [%s] %s" fullkey
|
||||
(propertize name 'face
|
||||
(if (and qcounts (plist-get qcounts :favorite))
|
||||
'mu4e-header-key-face nil)))
|
||||
fullkey)
|
||||
;; append all/unread numbers, if available.
|
||||
(if qcounts
|
||||
(let* ((unread (plist-get qcounts :unread))
|
||||
|
@ -203,32 +195,30 @@ clicked."
|
|||
(baseline-unread
|
||||
(or (when baseline (plist-get baseline :unread)) unread))
|
||||
(delta (- unread baseline-unread)))
|
||||
(format"%s (%s%s/%s)"
|
||||
(format "%s (%s%s/%s)"
|
||||
(make-string (- max-length (string-width name)) ? )
|
||||
(propertize
|
||||
(number-to-string unread) 'face 'mu4e-header-key-face
|
||||
'help-echo "Number of unread messages")
|
||||
(if (not mu4e-main-hide-baseline-delta)
|
||||
(propertize (format "/%+d" delta) 'face
|
||||
(if (> delta 0) 'mu4e-unread-face 'default)
|
||||
'help-echo "Unread messsages baseline-delta")
|
||||
"")
|
||||
(if (> delta 0)
|
||||
(propertize (format "(%+d)" delta) 'face
|
||||
'mu4e-unread-face) "")
|
||||
(propertize (number-to-string count)
|
||||
'help-echo "Total number of messages")))
|
||||
"") "\n"))
|
||||
|
||||
(defun mu4e--main-items (shortcut items max-length)
|
||||
"Display the entries for the bookmark/maildir menu.
|
||||
"Display the entries for the bookmark/maildir menu
|
||||
- SHORTCUT is a single character which is the first
|
||||
character of the keyboard shortcut
|
||||
- ITEMS is a list of items, for format see `(mu4e-bookmarks)'.
|
||||
- ITEMS is a list of items, for format see `(mu4e-bookmarks)'
|
||||
- MAX-LENGTH is the maximum length for an item name
|
||||
(used for alignment)."
|
||||
(cl-loop for item in items
|
||||
for fullkey = (format "%c%c" shortcut (plist-get item :key))
|
||||
for name = (plist-get item :name)
|
||||
for query = (funcall (or mu4e-query-rewrite-function #'identity)
|
||||
(plist-get item :query))
|
||||
(mu4e--bookmark-query item))
|
||||
for qcounts = (mu4e-last-query-result query)
|
||||
for unread = (and qcounts (plist-get (car qcounts) :unread))
|
||||
when (not (plist-get item :hide))
|
||||
|
@ -246,22 +236,17 @@ character of the keyboard shortcut
|
|||
(propertize (concat " " unit) 'face 'mu4e-header-title-face)
|
||||
"") "\n"))
|
||||
|
||||
;; NEW This is the old `mu4e--main-view' function but without
|
||||
;; buffer switching at the end.
|
||||
(defun mu4e--main-view-real (_ignore-auto _noconfirm)
|
||||
"The revert buffer function for `mu4e-main-mode'."
|
||||
(mu4e--main-view-real-1 'refresh))
|
||||
|
||||
(declare-function mu4e--start "mu4e")
|
||||
|
||||
(defun mu4e--main-view-real-1 (&optional refresh)
|
||||
"Create `mu4e-main-buffer-name' and set it up.
|
||||
When REFRESH is non nil refresh infos from server."
|
||||
(let ((inhibit-read-only t))
|
||||
;; Maybe refresh infos from server.
|
||||
(if refresh
|
||||
(mu4e--start 'mu4e--main-redraw-buffer)
|
||||
(mu4e--main-redraw-buffer))))
|
||||
(defun mu4e--baseline-time-string ()
|
||||
"Calculate the baseline time string."
|
||||
(let* ((baseline-t mu4e--baseline-tstamp)
|
||||
(updated-t (plist-get mu4e-index-update-status :tstamp))
|
||||
(delta-t (and baseline-t updated-t
|
||||
(float-time (time-subtract updated-t baseline-t)))))
|
||||
(if (and delta-t (> delta-t 0))
|
||||
(format-seconds "%Y %D %H %M %z%S ago" delta-t)
|
||||
(if baseline-t
|
||||
(current-time-string baseline-t)
|
||||
"Never"))))
|
||||
|
||||
(defun mu4e--main-redraw-buffer ()
|
||||
"Redraw the main buffer."
|
||||
|
@ -276,7 +261,7 @@ When REFRESH is non nil refresh infos from server."
|
|||
(propertize "mu4e" 'face 'mu4e-header-key-face)
|
||||
(propertize " - mu for emacs version " 'face 'mu4e-title-face)
|
||||
(propertize mu4e-mu-version 'face 'mu4e-header-key-face)
|
||||
"\n\n"
|
||||
"\n\n"
|
||||
(propertize " Basics\n\n" 'face 'mu4e-title-face)
|
||||
(mu4e--main-action-str
|
||||
"\t* [j]ump to some maildir\n" #'mu4e~headers-jump-to-maildir)
|
||||
|
@ -294,13 +279,12 @@ When REFRESH is non nil refresh infos from server."
|
|||
(propertize " Misc\n\n" 'face 'mu4e-title-face)
|
||||
|
||||
(mu4e--main-action-str "\t* [;]Switch context\n"
|
||||
(lambda()(interactive)
|
||||
(mu4e-context-switch)(revert-buffer)))
|
||||
(lambda()(interactive)
|
||||
(mu4e-context-switch)(revert-buffer)))
|
||||
|
||||
(mu4e--main-action-str "\t* [U]pdate email & database\n"
|
||||
#'mu4e-update-mail-and-index)
|
||||
(mu4e--main-action-str "\t* [R]eset query-results baseline\n"
|
||||
#'mu4e--main-reset-baseline-query-results)
|
||||
#'mu4e-update-mail-and-index)
|
||||
(mu4e--main-action-str "\t* [R]eset baseline\n" #'mu4e--reset-baseline)
|
||||
|
||||
;; show the queue functions if `smtpmail-queue-dir' is defined
|
||||
(if (file-directory-p smtpmail-queue-dir)
|
||||
|
@ -317,19 +301,17 @@ When REFRESH is non nil refresh infos from server."
|
|||
(mu4e--key-val "last updated"
|
||||
(current-time-string
|
||||
(plist-get mu4e-index-update-status :tstamp)))
|
||||
(if (and (not mu4e-main-hide-baseline-delta)
|
||||
mu4e--baseline-query-results-tstamp)
|
||||
(mu4e--key-val "baseline"
|
||||
(current-time-string mu4e--baseline-query-results-tstamp))
|
||||
(if mu4e--baseline-tstamp
|
||||
(mu4e--key-val "baseline" (mu4e--baseline-time-string))
|
||||
"")
|
||||
(mu4e--key-val "database-path" (mu4e-database-path))
|
||||
(mu4e--key-val "maildir" (mu4e-root-maildir))
|
||||
(mu4e--key-val "in store"
|
||||
(format "%d" (plist-get mu4e--server-props :doccount))
|
||||
"messages")
|
||||
(format "%d" (plist-get mu4e--server-props :doccount))
|
||||
"messages")
|
||||
(if mu4e-main-hide-personal-addresses ""
|
||||
(mu4e--key-val "personal addresses"
|
||||
(if addrs (mapconcat #'identity addrs ", " ) "none"))))
|
||||
(if addrs (mapconcat #'identity addrs ", " ) "none"))))
|
||||
|
||||
(if mu4e-main-hide-personal-addresses ""
|
||||
(unless (mu4e-personal-address-p user-mail-address)
|
||||
|
@ -368,26 +350,31 @@ When REFRESH is non nil refresh infos from server."
|
|||
(count-lines (point-min) (point-max)))
|
||||
(error 0)))
|
||||
|
||||
(declare-function mu4e--start "mu4e")
|
||||
|
||||
(defun mu4e--main-view (&optional refresh)
|
||||
"Create the mu4e main-view, and switch to it or show the menu.
|
||||
"Create or refresh the mu4e main-view, and switch to it.
|
||||
When REFRESH is non nil refresh infos from server.
|
||||
|
||||
If `mu4e-split-view' equals \='single-window, show a mu4e menu
|
||||
instead."
|
||||
(mu4e--reset-baseline)
|
||||
(if (eq mu4e-split-view 'single-window)
|
||||
(mu4e--main-menu)
|
||||
(let ((buf (get-buffer-create mu4e-main-buffer-name)))
|
||||
(let ((buf (get-buffer-create mu4e-main-buffer-name))
|
||||
(inhibit-read-only t))
|
||||
;; `mu4e--main-view' is called from `mu4e--start', so don't call it
|
||||
;; a second time here i.e. do not refresh unless specified
|
||||
;; explicitly with REFRESH arg.
|
||||
(with-current-buffer buf
|
||||
(mu4e--main-view-real-1 refresh))
|
||||
(if refresh
|
||||
(mu4e--start 'mu4e--main-redraw-buffer)
|
||||
(mu4e--main-redraw-buffer)))
|
||||
(mu4e-display-buffer buf t)
|
||||
(goto-char (point-min)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Interactive functions
|
||||
;; NEW
|
||||
;; Toggle mail sending mode without switching
|
||||
(defun mu4e--main-toggle-mail-sending-mode ()
|
||||
"Toggle sending mail mode, either queued or direct."
|
||||
|
@ -409,7 +396,7 @@ instead."
|
|||
'(("jump" . mu4e~headers-jump-to-maildir)
|
||||
("search" . mu4e-search)
|
||||
("Compose" . mu4e-compose-new)
|
||||
("bookmarks" . mu4e-headers-search-bookmark)
|
||||
("bookmarks" . mu4e-search-bookmark)
|
||||
(";Switch context" . mu4e-context-switch)
|
||||
("Update" . mu4e-update-mail-and-index)
|
||||
("News" . mu4e-news)
|
||||
|
@ -420,11 +407,5 @@ instead."
|
|||
(sit-for 1)
|
||||
(mu4e--main-menu))))
|
||||
|
||||
(defun mu4e--main-update-after-index ()
|
||||
"Update the main view buffer after indexing."
|
||||
(when (buffer-live-p mu4e-main-buffer-name)
|
||||
(with-current-buffer mu4e-main-buffer-name
|
||||
(revert-buffer))))
|
||||
|
||||
(provide 'mu4e-main)
|
||||
;;; mu4e-main.el ends here
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
;;; mu4e-modeline.el -- part of mu4e -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
|
||||
;; mu4e is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; mu4e is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with mu4e. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This file contains functionality for putting mu4e-related information
|
||||
;; in the emacs modeline, both buffer-specific and globally.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(defvar-local mu4e--modeline-buffer-items nil
|
||||
"List of buffer-local items for the mu4e modeline.
|
||||
Each element is function that evaluates to a string.")
|
||||
|
||||
(defvar mu4e--modeline-global-items nil
|
||||
"List of items for the global modeline.
|
||||
Each element is function that evaluates to a string.")
|
||||
|
||||
(defun mu4e--modeline-register (func &optional global)
|
||||
"Register a function for calculating some mu4e modeline part.
|
||||
If GLOBAL is non-nil, add to the global-modeline; otherwise use
|
||||
the buffer-local one."
|
||||
(add-to-list
|
||||
(if global 'mu4e--modeline-global-items 'mu4e--modeline-buffer-items)
|
||||
func))
|
||||
|
||||
(defvar mu4e--modeline-item nil
|
||||
"Mu4e item for the global-mode-line.")
|
||||
|
||||
(defun mu4e--modeline-string ()
|
||||
"Calculate the current mu4e modeline string."
|
||||
(mapconcat
|
||||
(lambda (item)
|
||||
(if (functionp item)
|
||||
(or (funcall item) "")
|
||||
""))
|
||||
(append mu4e--modeline-buffer-items mu4e--modeline-global-items) " "))
|
||||
|
||||
(define-minor-mode mu4e-modeline-mode
|
||||
"Minor mode for showing mu4e information on the modeline."
|
||||
;; This is a bit special 'global' mode, since it consists of both
|
||||
;; buffer-specific parts (mu4e--modeline-buffer-items) and global items
|
||||
;; (mu4e--modeline-global-items).
|
||||
:global t
|
||||
:group 'mu4e
|
||||
:lighter nil
|
||||
(if mu4e-modeline-mode
|
||||
(progn
|
||||
(setq mu4e--modeline-item '(:eval (mu4e--modeline-string)))
|
||||
(add-to-list 'global-mode-string mu4e--modeline-item))
|
||||
(progn
|
||||
(setq global-mode-string
|
||||
(seq-remove (lambda (item) (equal item mu4e--modeline-item))
|
||||
global-mode-string))))
|
||||
(force-mode-line-update))
|
||||
|
||||
(provide 'mu4e-modeline)
|
||||
;; mu4e-modeline.el ends here
|
|
@ -148,6 +148,8 @@
|
|||
(define-obsolete-function-alias 'mu4e-read-query
|
||||
'mu4e-search-read-query "1.7.0")
|
||||
|
||||
(make-obsolete-variable 'mu4e-display-update-status-in-modeline
|
||||
"No longer used" "1.9.11")
|
||||
|
||||
;; mu4e-headers
|
||||
(make-obsolete-variable 'mu4e-headers-field-properties-function
|
||||
|
|
|
@ -165,8 +165,7 @@ but also manually invoked searches."
|
|||
;;; History
|
||||
(defvar mu4e--search-query-past nil
|
||||
"Stack of queries before the present one.")
|
||||
(defvar mu4e--search-query-future nil
|
||||
"Stack of queries after the present one.")
|
||||
(defvar mu4e--search-query-future nil "Stack of queries after the present one.")
|
||||
(defvar mu4e--search-query-stack-size 20
|
||||
"Maximum size for the query stacks.")
|
||||
(defvar mu4e--search-last-query nil
|
||||
|
@ -217,9 +216,14 @@ show the message with MSGID."
|
|||
If EDIT is non-nil, let the user edit the bookmark before starting
|
||||
the search."
|
||||
(interactive)
|
||||
(let ((expr
|
||||
(let* ((expr
|
||||
(or expr
|
||||
(mu4e-ask-bookmark (if edit "Select bookmark: " "Bookmark: ")))))
|
||||
(mu4e-ask-bookmark (if edit "Select bookmark: " "Bookmark: "))))
|
||||
(fav (mu4e--bookmark-query (mu4e-favorite-bookmark))))
|
||||
;; reset baseline when searching for bookmark query
|
||||
(when (and fav (string= fav expr))
|
||||
(mu4e--reset-baseline))
|
||||
|
||||
(run-hook-with-args 'mu4e-search-bookmark-hook expr)
|
||||
(mu4e-search expr (when edit "Edit bookmark: ") edit)))
|
||||
|
||||
|
|
|
@ -132,12 +132,55 @@ from the server process.")
|
|||
(defvar mu4e-pong-func nil
|
||||
"Function called for each (:pong type ....) sexp received.")
|
||||
|
||||
(defvar mu4e-queries-func nil
|
||||
"Function called for each (:queries type ....) sexp received.")
|
||||
|
||||
(defvar mu4e-contacts-func nil
|
||||
"A function called for each (:contacts (<list-of-contacts>))
|
||||
sexp received from the server process.")
|
||||
|
||||
|
||||
;;; Internal vars
|
||||
;;; Dealing with Server properties
|
||||
(defvar mu4e--server-props nil
|
||||
"Metadata we receive from the mu4e server.")
|
||||
|
||||
(defun mu4e-server-properties ()
|
||||
"Get the server metadata plist."
|
||||
mu4e--server-props)
|
||||
|
||||
(defun mu4e-root-maildir()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :root-maildir))
|
||||
(mu4e-error "Root maildir unknown; did you start mu4e?")))
|
||||
|
||||
(defun mu4e-database-path()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :database-path))
|
||||
(mu4e-error "Root maildir unknown; did you start mu4e?")))
|
||||
|
||||
(defun mu4e-server-version()
|
||||
"Get the root maildir."
|
||||
(or (and mu4e--server-props
|
||||
(plist-get mu4e--server-props :version))
|
||||
(mu4e-error "Version unknown; did you start mu4e?")))
|
||||
|
||||
;;
|
||||
;; server-query-results are the results from the counting-queries
|
||||
;; we do for bookmarks etc. to populate the main view with unread
|
||||
;; counts.
|
||||
|
||||
;;; remember queries result.
|
||||
(defvar mu4e--server-query-results nil
|
||||
"Metadata we receive from the mu4e server.")
|
||||
|
||||
(defun mu4e-server-query-results ()
|
||||
"Get the latest server queries list."
|
||||
mu4e--server-query-results)
|
||||
|
||||
|
||||
;;; Handling raw server data
|
||||
|
||||
(defvar mu4e--server-buf nil
|
||||
"Buffer (string) for data received from the backend.")
|
||||
|
@ -164,8 +207,7 @@ Match 1 will be the length (in hex).")
|
|||
Checks whether the server process is live."
|
||||
(and mu4e--server-process
|
||||
(memq (process-status mu4e--server-process)
|
||||
'(run open listen connect stop))
|
||||
t))
|
||||
'(run open listen connect stop)) t))
|
||||
|
||||
(defsubst mu4e--server-eat-sexp-from-buf ()
|
||||
"'Eat' the next s-expression from `mu4e--server-buf'.
|
||||
|
@ -286,9 +328,14 @@ The server output is as follows:
|
|||
|
||||
;; received a pong message
|
||||
((plist-get sexp :pong)
|
||||
(mu4e--update-server-props (plist-get sexp :props))
|
||||
(setq mu4e--server-props (plist-get sexp :props))
|
||||
(funcall mu4e-pong-func sexp))
|
||||
|
||||
;; receive queries info
|
||||
((plist-get sexp :queries)
|
||||
(setq mu4e--server-query-results (plist-get sexp :queries))
|
||||
(funcall mu4e-queries-func sexp))
|
||||
|
||||
;; received a contacts message
|
||||
;; note: we use 'member', to match (:contacts nil)
|
||||
((plist-member sexp :contacts)
|
||||
|
@ -562,11 +609,15 @@ Returns either (:update ... ) or (:error ) sexp, which are handled my
|
|||
:rename ,(and maildir mu4e-change-filenames-when-moving t)
|
||||
:no-view ,(and no-view t))))
|
||||
|
||||
(defun mu4e--server-ping (&optional queries)
|
||||
"Sends a ping to the mu server, expecting a (:pong ...) in response.
|
||||
(defun mu4e--server-ping ()
|
||||
"Sends a ping to the mu server, expecting a (:pong ...) in response."
|
||||
(mu4e--server-call-mu `(ping)))
|
||||
|
||||
(defun mu4e--server-queries (queries)
|
||||
"Sends queries to the mu server, expecting a (:queries ...) in response.
|
||||
QUERIES is a list of queries for the number of results with
|
||||
read/unread status are returned in the pong-response."
|
||||
(mu4e--server-call-mu `(ping :queries ,queries)))
|
||||
(mu4e--server-call-mu `(queries :queries ,queries)))
|
||||
|
||||
(defun mu4e--server-remove (docid)
|
||||
"Remove message with DOCID.
|
||||
|
|
|
@ -311,7 +311,6 @@ run in the background; otherwise, pop up a window."
|
|||
:lighter ""
|
||||
:keymap
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "C-c C-r") #'mu4e-reset-baseline-query-results)
|
||||
(define-key map (kbd "C-S-u") #'mu4e-update-mail-and-index)
|
||||
;; for terminal users
|
||||
(define-key map (kbd "C-c C-u") #'mu4e-update-mail-and-index)
|
||||
|
|
78
mu4e/mu4e.el
78
mu4e/mu4e.el
|
@ -1,6 +1,6 @@
|
|||
;;; mu4e.el --- part of mu4e, the mu mail user agent -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2011-2022 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2023 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
|
@ -48,6 +48,11 @@
|
|||
:type 'boolean
|
||||
:group 'mu4e)
|
||||
|
||||
(defcustom mu4e-modeline-support t
|
||||
"Support for shoiwing information in the modeline."
|
||||
:type 'boolean
|
||||
:group 'mu4e)
|
||||
|
||||
(defcustom mu4e-org-support t
|
||||
"Support Org-mode links."
|
||||
:type 'boolean
|
||||
|
@ -68,6 +73,7 @@
|
|||
(with-eval-after-load 'desktop
|
||||
(eval '(add-to-list 'desktop-modes-not-to-save 'mu4e-compose-mode)))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun mu4e (&optional background)
|
||||
"If mu4e is not running yet, start it.
|
||||
|
@ -76,12 +82,11 @@ is non-nil."
|
|||
(interactive "P")
|
||||
;; start mu4e, then show the main view
|
||||
(mu4e--init-handlers)
|
||||
|
||||
;; i.e., only auto update baseline when user explicitly requested
|
||||
(when (and mu4e-main-auto-reset-baseline
|
||||
(not background) (called-interactively-p 'interactive))
|
||||
(mu4e-reset-baseline-query-results))
|
||||
|
||||
(when (or (not mu4e--baseline-tstamp)
|
||||
(and (not background) (called-interactively-p 'interactive)))
|
||||
(mu4e--reset-baseline))
|
||||
(mu4e--modeline-update)
|
||||
(mu4e--start (unless background 'mu4e--main-view)))
|
||||
|
||||
(defun mu4e-quit()
|
||||
|
@ -133,6 +138,34 @@ Invoke FUNC if non-nil."
|
|||
(lambda () (mu4e-update-mail-and-index
|
||||
mu4e-index-update-in-background)))))))
|
||||
|
||||
(defun mu4e--server-bookmarks-queries()
|
||||
(mu4e--server-queries
|
||||
(mapcar ;; send it a list of queries we'd like to see read/unread info for
|
||||
(lambda (bm)
|
||||
(funcall (or mu4e-query-rewrite-function #'identity)
|
||||
(mu4e--bookmark-query bm)))
|
||||
;; exclude bookmarks with certain flags
|
||||
(seq-filter (lambda (bm)
|
||||
(and (not (or (plist-get bm :hide)
|
||||
(plist-get bm :hide-unread)))))
|
||||
(append (mu4e-bookmarks)
|
||||
(mu4e--maildirs-with-query))))))
|
||||
|
||||
(defun mu4e--queries-handler (_sexp)
|
||||
;; we've received new server-queries; so update the main view
|
||||
;; (if any) and the modeline.
|
||||
|
||||
;; 1. update the query results (i.e. process the new server queries)
|
||||
(mu4e-last-query-results 'force-update)
|
||||
(unless mu4e--baseline
|
||||
(mu4e--reset-baseline))
|
||||
(mu4e--modeline-update)
|
||||
|
||||
;; 2. update the main view, if any
|
||||
(when (buffer-live-p mu4e-main-buffer-name)
|
||||
(with-current-buffer mu4e-main-buffer-name
|
||||
(revert-buffer))))
|
||||
|
||||
(defun mu4e--start (&optional func)
|
||||
"Start mu4e.
|
||||
If `mu4e-contexts' have been defined, but we don't have a context
|
||||
|
@ -144,18 +177,10 @@ Otherwise, check requirements, then start mu4e. When successful, invoke
|
|||
(unless (mu4e-context-current)
|
||||
(mu4e--context-autoswitch nil mu4e-context-policy))
|
||||
(setq mu4e-pong-func (lambda (info) (mu4e--pong-handler info func)))
|
||||
(mu4e--server-ping
|
||||
(mapcar ;; send it a list of queries we'd like to see read/unread info for
|
||||
(lambda (bm)
|
||||
(funcall (or mu4e-query-rewrite-function #'identity)
|
||||
(plist-get bm :query)))
|
||||
;; exclude bookmarks that are not strings, and with certain flags
|
||||
(seq-filter (lambda (bm)
|
||||
(and (stringp (plist-get bm :query))
|
||||
(not (or (plist-get bm :hide)
|
||||
(plist-get bm :hide-unread)))))
|
||||
(append (mu4e-bookmarks)
|
||||
(mu4e--maildirs-with-query)))))
|
||||
(mu4e--modeline-register #'mu4e--bookmarks-modeline-item 'global)
|
||||
(mu4e-modeline-mode (if mu4e-modeline-support 1 -1))
|
||||
(mu4e--server-bookmarks-queries)
|
||||
(mu4e--server-ping)
|
||||
;; maybe request the list of contacts, automatically refreshed after
|
||||
;; reindexing
|
||||
(unless mu4e--contacts-set (mu4e--request-contacts-maybe)))
|
||||
|
@ -166,6 +191,8 @@ Otherwise, check requirements, then start mu4e. When successful, invoke
|
|||
(cancel-timer mu4e--update-timer)
|
||||
(setq mu4e--update-timer nil))
|
||||
(mu4e-clear-caches)
|
||||
|
||||
(mu4e-modeline-mode -1)
|
||||
(mu4e--server-kill)
|
||||
;; kill all mu4e buffers
|
||||
(mapc
|
||||
|
@ -185,7 +212,7 @@ Otherwise, check requirements, then start mu4e. When successful, invoke
|
|||
;;; Handlers
|
||||
(defun mu4e--default-handler (&rest args)
|
||||
"Dummy handler function with arbitrary ARGS."
|
||||
(mu4e-error "Not handled: %S" args))
|
||||
(mu4e-error "Not handled: %s" args))
|
||||
|
||||
(defun mu4e--error-handler (errcode errmsg)
|
||||
"Handler function for showing an error with ERRCODE and ERRMSG."
|
||||
|
@ -222,6 +249,8 @@ Otherwise, check requirements, then start mu4e. When successful, invoke
|
|||
"%s completed; checked %d, updated %d, cleaned-up %d"
|
||||
(if mu4e-index-lazy-check "Lazy indexing" "Indexing")
|
||||
checked updated cleaned-up)
|
||||
;; index done; grab updated queries
|
||||
(mu4e--server-bookmarks-queries)
|
||||
(run-hooks 'mu4e-index-updated-hook)
|
||||
;; backward compatibility...
|
||||
(unless (zerop (+ updated cleaned-up))
|
||||
|
@ -248,11 +277,12 @@ chance."
|
|||
(mu4e-setq-if-nil mu4e-found-func #'mu4e~headers-found-handler)
|
||||
(mu4e-setq-if-nil mu4e-erase-func #'mu4e~headers-clear)
|
||||
|
||||
(mu4e-setq-if-nil mu4e-sent-func #'mu4e--default-handler)
|
||||
(mu4e-setq-if-nil mu4e-compose-func #'mu4e~compose-handler)
|
||||
(mu4e-setq-if-nil mu4e-contacts-func #'mu4e--update-contacts)
|
||||
(mu4e-setq-if-nil mu4e-info-func #'mu4e--info-handler)
|
||||
(mu4e-setq-if-nil mu4e-pong-func #'mu4e--default-handler))
|
||||
(mu4e-setq-if-nil mu4e-sent-func #'mu4e--default-handler)
|
||||
(mu4e-setq-if-nil mu4e-compose-func #'mu4e~compose-handler)
|
||||
(mu4e-setq-if-nil mu4e-contacts-func #'mu4e--update-contacts)
|
||||
(mu4e-setq-if-nil mu4e-info-func #'mu4e--info-handler)
|
||||
(mu4e-setq-if-nil mu4e-pong-func #'mu4e--default-handler)
|
||||
(mu4e-setq-if-nil mu4e-queries-func #'mu4e--queries-handler))
|
||||
|
||||
(defun mu4e-clear-caches ()
|
||||
"Clear any cached resources."
|
||||
|
|
452
mu4e/mu4e.texi
452
mu4e/mu4e.texi
|
@ -12,7 +12,7 @@
|
|||
@c %**end of header
|
||||
|
||||
@copying
|
||||
Copyright @copyright{} 2012-2022 Dirk-Jan C. Binnema
|
||||
Copyright @copyright{} 2012-2023 Dirk-Jan C. Binnema
|
||||
|
||||
@quotation
|
||||
Permission is granted to copy, distribute and/or modify this document
|
||||
|
@ -80,7 +80,7 @@ basic configuration and explain its daily use. We also show you how you
|
|||
can customize @t{mu4e} for your special needs.
|
||||
|
||||
At the end of the manual, there are some example configurations, to get
|
||||
you up to speed quickly: @ref{Example configs}. There's also a section
|
||||
you up to speed quickly: @ref{Example configurations}. There's also a section
|
||||
with answers to frequently asked questions, @ref{FAQ}.
|
||||
|
||||
@menu
|
||||
|
@ -99,25 +99,24 @@ with answers to frequently asked questions, @ref{FAQ}.
|
|||
|
||||
Appendices
|
||||
* Other tools:: mu4e and the rest of the world
|
||||
* Example configs:: Some examples to set you up quickly
|
||||
* Example configurations:: Some examples to set you up quickly
|
||||
* FAQ:: Common questions and answers
|
||||
* Tips and Tricks:: Useful tips
|
||||
* How it works:: Some notes about the implementation of @t{mu4e}
|
||||
* Debugging:: How to debug problems in @t{mu4e}
|
||||
* GNU Free Documentation License:: The license of this manual
|
||||
|
||||
@c Indices
|
||||
Indices
|
||||
@c * Command Index:: An item for each standard command name.
|
||||
@c * Variable Index:: An item for each variable documented in this manual.
|
||||
@c * Concept Index:: An item for concepts and other general subjects.
|
||||
* Concept Index:: Index of @t{mu4e} concepts and other general subjects.
|
||||
|
||||
@end menu
|
||||
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
Let's get started!
|
||||
|
||||
Let's get started!q
|
||||
@menu
|
||||
* Why another e-mail client::Aren't there enough already
|
||||
* Other mail clients::Where @t{mu4e} takes its inspiration from
|
||||
|
@ -316,7 +315,7 @@ Note: if you are familiar with @t{meson}, you can of course use its
|
|||
commands directly; the @t{make} commands are just a thin wrapper around
|
||||
that.
|
||||
|
||||
@subsection Installing
|
||||
@subsection Installation
|
||||
|
||||
After this, @t{mu} and @t{mu4e} should be installed @footnote{there's a
|
||||
hard dependency between versions of @t{mu4e} and @t{mu} --- you cannot
|
||||
|
@ -337,7 +336,7 @@ configuration before trying again:
|
|||
|
||||
There is some support for using the Emacs customization system in
|
||||
@t{mu4e}, but for now, we recommend setting the values manually. Please
|
||||
refer to @ref{Example configs} for a couple of examples of this; here we
|
||||
refer to @ref{Example configurations} for a couple of examples of this; here we
|
||||
go through things step-by-step.
|
||||
|
||||
@node Getting mail
|
||||
|
@ -394,7 +393,7 @@ You can add some e-mail addresses, so @t{mu} recognizes them as yours:
|
|||
indexing messages. If you want to change them, you need to @t{init}
|
||||
once again.
|
||||
|
||||
The addresses may also be basic POSIX regular expressions, wrapped in
|
||||
The addresses may also be basic PCRE regular expressions, wrapped in
|
||||
slashes, for example:
|
||||
|
||||
@example
|
||||
|
@ -603,7 +602,7 @@ For sending mail using @abbr{SMTP}, @t{mu4e} uses @t{smtpmail}
|
|||
send mail; please refer to its documentation for the details.
|
||||
|
||||
Here, we only provide some simple examples --- for more, see
|
||||
@ref{Example configs}.
|
||||
@ref{Example configurations}.
|
||||
|
||||
A very minimal setup:
|
||||
|
||||
|
@ -716,18 +715,18 @@ The main view looks something like the following:
|
|||
|
||||
Bookmarks
|
||||
|
||||
* [bu] Unread messages (13085/+3/13085)
|
||||
* [bu] Unread messages (13085(+3)/13085)
|
||||
* [bt] Today's messages
|
||||
* [bw] Last 7 days (53/+3/128)
|
||||
* [bp] Messages with images (75/-2/2441)
|
||||
* [bw] Last 7 days (53(+3)/128)
|
||||
* [bp] Messages with images (75/2441)
|
||||
|
||||
Maildirs
|
||||
|
||||
* [ja] /archive (2101/0/18837)
|
||||
* [ji] /inbox (8/+2/10)
|
||||
* [jb] /bulk (33/+0/35)
|
||||
* [jB] /bulkarchive (179/+0/2090)
|
||||
* [jm] /mu (694/+1/17687)
|
||||
* [ja] /archive (2101/18837)
|
||||
* [ji] /inbox (8(+2)/10)
|
||||
* [jb] /bulk (33/35)
|
||||
* [jB] /bulkarchive (179/2090)
|
||||
* [jm] /mu (694(+1)/17687)
|
||||
* [jn] /sauron
|
||||
* [js] /sent
|
||||
|
||||
|
@ -780,26 +779,30 @@ the @ref{Editor view} to write a new message.
|
|||
|
||||
The next two items in the Main view are @emph{Bookmarks} and @emph{Maildirs}.
|
||||
|
||||
Bookmarks are predefined queries with a descriptive name and a
|
||||
shortcut --- in the example above, we see the default bookmarks. You
|
||||
can view the list of messages matching a certain bookmark by pressing
|
||||
@key{b} followed by the bookmark's shortcut. If you'd like to edit the
|
||||
bookmarked query first before invoking it, use @key{B}.
|
||||
Bookmarks are predefined queries with a descriptive name and a shortcut --- in
|
||||
the example above, we see the default bookmarks. You can view the list of
|
||||
messages matching a certain bookmark by pressing @key{b} followed by the
|
||||
bookmark's shortcut. If you want to edit the bookmarked query before invoking
|
||||
it, use @key{B}.
|
||||
|
||||
Next to each bookmark there is the number of (unread/delta/all) messages that
|
||||
match.
|
||||
Next to each bookmark are some numbers that indicate the (unread(delta)/all)
|
||||
matching messages for the given query, with the delta being the difference in
|
||||
unread count since some ``baseline'', and only shown when this delta > 0.
|
||||
|
||||
The ``unread'' and ``all'' have their obvious meaning; the @emph{delta} is the
|
||||
difference in unread messages since ``baseline'', which is the state at some
|
||||
point in the past. This delta is useful to quickly see what changed since the
|
||||
last time you looked.
|
||||
Note that the ``delta'' has its limitations: if you, for instance, deleted 5
|
||||
messages and received 5 new one, the ``delta'' would be 0, although there were
|
||||
changes indeed. So it is mostly useful for tracking changes while you are
|
||||
@emph{not} using @t{mu4e}.
|
||||
|
||||
By default, the baseline is automatically reset when switching to the main view
|
||||
explicitly; otherwise the baseline can be reset with
|
||||
@code{mu4e-reset-baseline-query-results}, which is bound to @kbd{R} in the
|
||||
main-view, and @kbd{C-c C-R} throughout @t{mu4e}. You can customize the behavior
|
||||
using @var{mu4e-main-hide-baseline-delta} and
|
||||
@var{mu4e-main-auto-reset-baseline}.
|
||||
This delta is useful to quickly see that there are new messages since the last
|
||||
time you looked. Imagine switching to another buffer to work on something or
|
||||
even (!) stepping away from your computer to return later: the baseline allows
|
||||
you to quickly see what changed.
|
||||
|
||||
By default, the baseline is reset automatically when switching to the main view
|
||||
explicitly (but see @code{mu4e-main-auto-reset-baseline}. It can also be reset
|
||||
explicitly using @code{mu4e-reset-baseline-query-results}, which is bound to
|
||||
@kbd{R} in the main-view.
|
||||
|
||||
Bookmarks are stored in the variable @code{mu4e-bookmarks}; you can add
|
||||
your own and/or replace the default ones; @xref{Bookmarks}. For
|
||||
|
@ -812,14 +815,17 @@ instance:
|
|||
:query "list:mu-discuss.googlegroups.com AND date:7d..now"))
|
||||
@end lisp
|
||||
|
||||
There are optional keys @t{:hide} to hide the bookmark from the main
|
||||
menu, but still have it available (using @key{b})) and
|
||||
@t{:hide-unread} to avoid generating the unread-number; that can be
|
||||
useful if you have bookmarks for slow queries. Note that
|
||||
@t{:hide-unread} is implied when the query is not a string; this for
|
||||
the common case where the query function involves some user input,
|
||||
There are optional keys @t{:hide} to hide the bookmark from the main menu, but
|
||||
still have it available (using @key{b})) and @t{:hide-unread} to avoid
|
||||
generating the unread-number; that can be useful if you have bookmarks for slow
|
||||
queries. Note that @t{:hide-unread} is implied when the query is not a string;
|
||||
this for the common case where the query function involves some user input,
|
||||
which would be disruptive in this case.
|
||||
|
||||
There is also the optional @code{:favorite} property, which at most one bookmark
|
||||
should have; this bookmark is highlighted in the main view, and its
|
||||
unread-status is shown in the modeline; @xref{Modeline}.
|
||||
|
||||
The Maildirs item is very similar to Bookmarks, when you consider maildirs here
|
||||
as being special kind of bookmark that matches some Maildir.
|
||||
|
||||
|
@ -1071,7 +1077,7 @@ Note that with threading enabled, the sorting is exclusively by date,
|
|||
regardless of the column clicked.
|
||||
|
||||
If you want to change the defaults for these settings, you can use the variables
|
||||
@var{mu4e-search-sort-field} and @var{mu4e-search-show-threads}, as well as
|
||||
@code{mu4e-search-sort-field} and @code{mu4e-search-show-threads}, as well as
|
||||
@code{mu4e-search-change-sorting} to change the sorting of the current search
|
||||
results.
|
||||
|
||||
|
@ -1740,7 +1746,7 @@ then still include the signature manually, using the function
|
|||
|
||||
@itemize
|
||||
@item If you want use @t{mu4e} as Emacs' default program for sending mail,
|
||||
see @ref{Emacs default}.
|
||||
see @ref{Default email client}.
|
||||
@item Normally, @t{mu4e} @emph{buries} the message buffer after sending; if you want
|
||||
to kill the buffer instead, add something like the following to your
|
||||
configuration:
|
||||
|
@ -2099,7 +2105,7 @@ query, so, effectively `widens' the search. Technically, narrowing the results
|
|||
of query @t{x} with expression @t{y} implies doing a search @t{(x) AND (y)}.
|
||||
|
||||
Note that messages that were not in your original search results because of
|
||||
@var{mu4e-search-results-limit} may show up in the narrowed query.
|
||||
@code{mu4e-search-results-limit} may show up in the narrowed query.
|
||||
|
||||
@subsection Including related messages
|
||||
@anchor{Including related messages}
|
||||
|
@ -2108,7 +2114,7 @@ It can be useful to not only show the messages that directly match a certain
|
|||
query, but also include messages that are related to these messages. That is,
|
||||
messages that belong to the same discussion threads are included in the results,
|
||||
just like e.g. Gmail does it. You can enable this behavior by setting
|
||||
@var{mu4e-search-include-related} to @code{t}, and you can toggle between
|
||||
@code{mu4e-search-include-related} to @code{t}, and you can toggle between
|
||||
including/not-including with @key{W}.
|
||||
|
||||
Be careful though when e.g. deleting ranges of messages from a certain
|
||||
|
@ -2123,7 +2129,7 @@ copies of messages, there's usually little value in including more than one in
|
|||
search results. A common reason for having multiple copies of messages is the
|
||||
combination of Gmail and @t{offlineimap}, since that is the way the labels /
|
||||
virtual folders in Gmail are represented. You can enable skipping duplicates by
|
||||
setting @var{mu4e-search-skip-duplicates} to @code{t}, and you can toggle
|
||||
setting @code{mu4e-search-skip-duplicates} to @code{t}, and you can toggle
|
||||
between the skipping/not skipping with @key{V}.
|
||||
|
||||
Note, messages are considered duplicates when they have the same
|
||||
|
@ -2265,8 +2271,8 @@ Custom mark functions are to be appended to the list
|
|||
@item The name of the marker --- a short string describing this marker. The
|
||||
first character of this string determines its shortcut, so these should be
|
||||
unique. If necessary, simply prefix the name with a unique character.
|
||||
@item a predicate function, taking two arguments @var{msg} and @var{param}.
|
||||
@var{msg} is the message plist (see @ref{Message functions}) and @var{param} is
|
||||
@item a predicate function, taking two arguments @code{msg} and @code{param}.
|
||||
@code{msg} is the message plist (see @ref{Message functions}) and @code{param} is
|
||||
a parameter provided by the third of the marker elements (see the next
|
||||
item). The predicate function should return non-@t{nil} if the message
|
||||
matches.
|
||||
|
@ -2575,8 +2581,8 @@ when starting; see the discussion in the previous section.
|
|||
A couple of notes about this example:
|
||||
@itemize
|
||||
@item You can manually switch the context use @code{M-x mu4e-context-switch},
|
||||
by default bound to @kbd{;} in headers, view and main mode.
|
||||
The current context appears in the mode-line.
|
||||
by default bound to @kbd{;} in headers, view and main mode. The current context
|
||||
appears in the modeline by default; see @ref{Modeline} for details.
|
||||
@item Normally, @code{M-x mu4e-context-switch} does not call the enter or
|
||||
leave functions if the 'new' context is the same as the old one.
|
||||
However, with a prefix-argument (@kbd{C-u}), you can force @t{mu4e} to
|
||||
|
@ -2713,11 +2719,10 @@ work-email. You can achieve this with something like:
|
|||
@noindent
|
||||
Good to remember:
|
||||
@itemize
|
||||
@item The @var{msg} parameter you receive in the function refers to the
|
||||
@emph{original message}, that is, the message being replied to or
|
||||
forwarded. When re-editing a message, it refers to the message being
|
||||
edited. When you compose a totally new message, the @var{msg} parameter is
|
||||
@code{nil}.
|
||||
@item The @code{msg} parameter you receive in the function refers to the
|
||||
@emph{original message}, that is, the message being replied to or forwarded.
|
||||
When re-editing a message, it refers to the message being edited. When you
|
||||
compose a totally new message, the @code{msg} parameter is @code{nil}.
|
||||
@item When re-editing messages, the value of @code{mu4e-drafts-folder} is ignored.
|
||||
@end itemize
|
||||
|
||||
|
@ -3052,32 +3057,84 @@ see @code{mu4e-toggle-logging}.
|
|||
@code{user-error} and @code{error} functions.
|
||||
@end itemize
|
||||
|
||||
@node Other tools
|
||||
@appendix Other tools
|
||||
@node Integrating with Emacs
|
||||
@chapter Integrating with Emacs
|
||||
|
||||
In this chapter, we discuss some ways in which @t{mu4e} can cooperate
|
||||
with other tools.
|
||||
In this chapter, we discuss how you can integrate @t{mu4e} with Emacs in various
|
||||
ways. Here we focus on Emacs built-ins; for dealing with external tools,
|
||||
@xref{Other tools}.
|
||||
|
||||
@menu
|
||||
* Emacs default::Making mu4e the default emacs e-mail program
|
||||
* Emacs bookmarks::Using Emacs' bookmark system
|
||||
* Modeline::Showing mu4e's status in the modeline
|
||||
* Default email client::Making mu4e the default emacs e-mail program
|
||||
* Using bookmarks::Using Emacs' bookmark system
|
||||
* Org-mode links::Adding mu4e to your organized life
|
||||
* Org-contacts::Hooking up with org-contacts
|
||||
* BBDB::Hooking up with the Insidious Big Brother Database
|
||||
* iCalendar::Enabling iCalendar invite processing
|
||||
* Sauron::Getting new mail notifications with Sauron
|
||||
* Speedbar::A special frame with your folders
|
||||
* Dired:: Attaching files using @t{dired}
|
||||
* Hydra:: Custom shortcut menus
|
||||
@end menu
|
||||
|
||||
@node Emacs default
|
||||
@section Emacs default
|
||||
@node Modeline
|
||||
@section Modeline
|
||||
@cindex modeline
|
||||
|
||||
Emacs allows you to select an e-mail program as the default
|
||||
program it uses when you press @key{C-x m} (@code{compose-mail}), call
|
||||
@code{report-emacs-bug} and so on. If you want to use @t{mu4e} for this,
|
||||
you can do so by adding the following to your configuration:
|
||||
One of the most visible ways in which @t{mu4e} integrates with Emacs is through
|
||||
the @emph{modeline} @xref{Mode Line,,,emacs}. The @t{mu4e} support for that is
|
||||
handled through a minor-mode @code{mu4e-modeline-mode}, which is enabled by
|
||||
default when @t{mu4e} is running.
|
||||
|
||||
To completely turn off the modeline support, set @code{mu4e-support-modeline} to
|
||||
@t{nil} before starting @t{mu4e}.
|
||||
|
||||
@t{mu4e} shares information on the modeline in two ways:
|
||||
@itemize
|
||||
@item buffer-specific: information about the search parameters and the current context
|
||||
@item global: information about unread messages
|
||||
@end itemize
|
||||
|
||||
The buffer-specific items should be fairly self-explanatory - they show,
|
||||
respectively, your search parameters and the current context.
|
||||
|
||||
@cindex favorite bookmark
|
||||
Since @t{mu4e} is a query-based email-client, there a lot of flexibilty in what
|
||||
you want to consider ``interesting new mail'', that is the, the query we want to
|
||||
monitor for changes.
|
||||
|
||||
The global modeline contains the results of some specific ``favorite'' bookmark
|
||||
query from @code{mu4e-bookmarks}. By default, the @emph{first} one in chosen,
|
||||
but you may want change that by using the @code{:favorite} property for a
|
||||
particular query, e.g., as part of @var{mu4e-bookmarks}:
|
||||
@example
|
||||
;; Monitor the inbox folder in the modeline
|
||||
(:query "maildir:/inbox" :name "Inbox" :key ?i :favorite t)
|
||||
@end example
|
||||
|
||||
The results of this query (the last time it was updated) is shows as some
|
||||
character or emoji (depending on @var{mu4e-use-fancy-chars}) and 2 or 3 numbers,
|
||||
just like what we saw in @xref{Bookmarks and Maildirs}, e.g.,
|
||||
@example
|
||||
N:10(+5)/15
|
||||
@end example
|
||||
|
||||
@cindex baseline query results
|
||||
this means there are 10 unread messages, with 5 new messages since the baseline,
|
||||
and in total 15 messages.
|
||||
|
||||
You can also customize the icon; see @var{mu4e-modeline-all-clear},
|
||||
@var{mu4e-modeline-all-read}, @var{mu4e-modeline-all-clear} and
|
||||
@var{mu4e-modeline-all-clear}
|
||||
|
||||
Due to the way queries work, the modeline is @emph{not} immediately updated when
|
||||
you read messages; but going back to the main view (with @kbd{M-x mu4e} restores
|
||||
things.
|
||||
|
||||
@node Default email client
|
||||
@section Default email client
|
||||
|
||||
Emacs allows you to select an e-mail program as the default program it uses when
|
||||
you press @key{C-x m} (@code{compose-mail}), call @code{report-emacs-bug} and so
|
||||
on. If you want to use @t{mu4e} for this, you can do so by adding the following
|
||||
to your configuration:
|
||||
|
||||
@lisp
|
||||
(setq mail-user-agent 'mu4e-user-agent)
|
||||
|
@ -3092,15 +3149,15 @@ mail, customize the variable @code{read-mail-command}.
|
|||
|
||||
(@pxref{Top,,Emacs,Sending Mail, Mail Methods})
|
||||
|
||||
@node Using bookmarks
|
||||
@section Using bookmarks
|
||||
|
||||
@node Emacs bookmarks
|
||||
@section Emacs bookmarks
|
||||
|
||||
@t{mu4e} supports linking to the message-at-point through the normal
|
||||
Emacs built-in bookmark system. The links are based on the message's
|
||||
message-id, and thus the bookmarks stay valid even if you move the
|
||||
message around.
|
||||
Note, emacs bookmarks are not to be confused with mu4e's bookmarks; the former
|
||||
are a generic linking system, while the latter are remember stored queries.
|
||||
|
||||
@t{mu4e} supports linking to the message-at-point through the normal Emacs
|
||||
built-in bookmark system. The links are based on the message's message-id, and
|
||||
thus the bookmarks stay valid even if you move the message around.
|
||||
|
||||
@node Org-mode links
|
||||
@section Org-mode links
|
||||
|
@ -3164,71 +3221,6 @@ key-bindings for that in headers and view mode:
|
|||
(define-key mu4e-view-mode-map (kbd "C-c c") 'mu4e-org-store-and-capture)
|
||||
@end lisp
|
||||
|
||||
|
||||
@node Org-contacts
|
||||
@section Org-contacts
|
||||
|
||||
Note, @t{mu4e} supports built-in address autocompletion; @ref{Address
|
||||
autocompletion}, and that is the recommended way to do this. However, it
|
||||
is also possible to manage your addresses with @t{org-mode}, using
|
||||
@t{org-contacts}@footnote{@url{https://julien.danjou.info/projects/emacs-packages#org-contacts}}.
|
||||
|
||||
@t{mu4e-actions} defines a useful action (@ref{Actions}) for adding a
|
||||
contact based on the @t{From:}-address in the message at point. To
|
||||
enable this, add to your configuration something like:
|
||||
|
||||
@lisp
|
||||
(setq mu4e-org-contacts-file <full-path-to-your-org-contacts-file>)
|
||||
(add-to-list 'mu4e-headers-actions
|
||||
'("org-contact-add" . mu4e-action-add-org-contact) t)
|
||||
(add-to-list 'mu4e-view-actions
|
||||
'("org-contact-add" . mu4e-action-add-org-contact) t)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
After this, you should be able to add contacts using @key{a o} in the
|
||||
headers view and the message view, using the @t{org-capture} mechanism.
|
||||
Note, the shortcut character @key{o} is due to the first character of
|
||||
@t{org-contact-add}.
|
||||
|
||||
@node BBDB
|
||||
@section BBDB
|
||||
|
||||
Note, @t{mu4e} supports built-in address autocompletion; @ref{Address
|
||||
autocompletion}, and that is the recommended way to do this. However, it
|
||||
is also possible to manage your addresses with the current (2015-06-23)
|
||||
development release of @t{BBDB}, or releases of @t{BBDB} after
|
||||
3.1.2.@footnote{@url{https://savannah.nongnu.org/projects/bbdb/}}.
|
||||
|
||||
To enable BBDB, add to your @file{~/.emacs} (or its moral equivalent,
|
||||
such as @file{~/.emacs.d/init.el}) the following @emph{after} the
|
||||
@code{(require 'mu4e)} line:
|
||||
|
||||
@lisp
|
||||
;; Load BBDB (Method 1)
|
||||
(require 'bbdb-loaddefs)
|
||||
;; OR (Method 2)
|
||||
;; (require 'bbdb-loaddefs "/path/to/bbdb/lisp/bbdb-loaddefs.el")
|
||||
;; OR (Method 3)
|
||||
;; (autoload 'bbdb-insinuate-mu4e "bbdb-mu4e")
|
||||
;; (bbdb-initialize 'message 'mu4e)
|
||||
|
||||
(setq bbdb-mail-user-agent 'mu4e-user-agent)
|
||||
(setq mu4e-view-rendered-hook 'bbdb-mua-auto-update)
|
||||
(setq mu4e-compose-complete-addresses nil)
|
||||
(setq bbdb-mua-pop-up t)
|
||||
(setq bbdb-mua-pop-up-window-size 5)
|
||||
(setq mu4e-view-show-addresses t)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
After this, you should be able to:
|
||||
@itemize
|
||||
@item In mu4e-view mode, add the sender of the email to BBDB with @key{C-u :}
|
||||
@item Tab-complete addresses from BBDB when composing emails
|
||||
@item View the BBDB contact while viewing a message
|
||||
@end itemize
|
||||
|
||||
@node iCalendar
|
||||
@section iCalendar
|
||||
|
||||
|
@ -3320,6 +3312,120 @@ functions use that to set the @code{datetree} location:
|
|||
If you do this, you'll want to omit the @code{:timeprompt t} setting
|
||||
from your capture template.
|
||||
|
||||
|
||||
@node Speedbar
|
||||
@section Speedbar
|
||||
@cindex speedbar
|
||||
|
||||
@code{speedbar} is an Emacs-extension that shows navigational
|
||||
information for an Emacs buffer in a separate frame. Using
|
||||
@code{mu4e-speedbar}, @t{mu4e} lists your bookmarks and maildir
|
||||
folders and allows for one-click access to them.
|
||||
|
||||
To enable this, add @t{(require 'mu4e-speedbar)} to your configuration;
|
||||
then, all you need to do to activate it is @kbd{M-x speedbar}. Then,
|
||||
when then switching to the @ref{Main view}, the speedbar-frame is
|
||||
updated with your bookmarks and maildirs.
|
||||
|
||||
For speed reasons, the list of maildirs is determined when @t{mu4e}
|
||||
starts; if the list of maildirs changes while @t{mu4e} is running, you
|
||||
need to restart @t{mu4e} to have those changes reflected in the speedbar
|
||||
and in other places that use this list, such as auto-completion when
|
||||
jumping to a maildir.
|
||||
|
||||
@node Dired
|
||||
@section Dired
|
||||
|
||||
It is possible to attach files to @t{mu4e} messages using @t{dired}
|
||||
(@ref{Dired,,emacs}), using the following steps (based on a post on
|
||||
the @t{mu-discuss} mailing list by @emph{Stephen Eglen}).
|
||||
|
||||
@lisp
|
||||
(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
|
||||
@end lisp
|
||||
|
||||
Then, mark the file(s) in @t{dired} you would like to attach and press
|
||||
@t{C-c RET C-a}, and you'll be asked whether to attach them to an
|
||||
existing message, or create a new one.
|
||||
|
||||
@node Other tools
|
||||
@appendix Other tools
|
||||
|
||||
In this chapter, we discuss some ways in which @t{mu4e} can cooperate
|
||||
with other tools.
|
||||
|
||||
@menu
|
||||
* Org-contacts::Hooking up with org-contacts
|
||||
* BBDB::Hooking up with the Insidious Big Brother Database
|
||||
* Sauron::Getting new mail notifications with Sauron
|
||||
* Hydra:: Custom shortcut menus
|
||||
@end menu
|
||||
|
||||
@node Org-contacts
|
||||
@section Org-contacts
|
||||
|
||||
Note, @t{mu4e} supports built-in address autocompletion; @ref{Address
|
||||
autocompletion}, and that is the recommended way to do this. However, it
|
||||
is also possible to manage your addresses with @t{org-mode}, using
|
||||
@t{org-contacts}@footnote{@url{https://julien.danjou.info/projects/emacs-packages#org-contacts}}.
|
||||
|
||||
@t{mu4e-actions} defines a useful action (@ref{Actions}) for adding a
|
||||
contact based on the @t{From:}-address in the message at point. To
|
||||
enable this, add to your configuration something like:
|
||||
|
||||
@lisp
|
||||
(setq mu4e-org-contacts-file <full-path-to-your-org-contacts-file>)
|
||||
(add-to-list 'mu4e-headers-actions
|
||||
'("org-contact-add" . mu4e-action-add-org-contact) t)
|
||||
(add-to-list 'mu4e-view-actions
|
||||
'("org-contact-add" . mu4e-action-add-org-contact) t)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
After this, you should be able to add contacts using @key{a o} in the
|
||||
headers view and the message view, using the @t{org-capture} mechanism.
|
||||
Note, the shortcut character @key{o} is due to the first character of
|
||||
@t{org-contact-add}.
|
||||
|
||||
@node BBDB
|
||||
@section BBDB
|
||||
|
||||
Note, @t{mu4e} supports built-in address autocompletion; @ref{Address
|
||||
autocompletion}, and that is the recommended way to do this. However, it
|
||||
is also possible to manage your addresses with the current (2015-06-23)
|
||||
development release of @t{BBDB}, or releases of @t{BBDB} after
|
||||
3.1.2.@footnote{@url{https://savannah.nongnu.org/projects/bbdb/}}.
|
||||
|
||||
To enable BBDB, add to your @file{~/.emacs} (or its moral equivalent,
|
||||
such as @file{~/.emacs.d/init.el}) the following @emph{after} the
|
||||
@code{(require 'mu4e)} line:
|
||||
|
||||
@lisp
|
||||
;; Load BBDB (Method 1)
|
||||
(require 'bbdb-loaddefs)
|
||||
;; OR (Method 2)
|
||||
;; (require 'bbdb-loaddefs "/path/to/bbdb/lisp/bbdb-loaddefs.el")
|
||||
;; OR (Method 3)
|
||||
;; (autoload 'bbdb-insinuate-mu4e "bbdb-mu4e")
|
||||
;; (bbdb-initialize 'message 'mu4e)
|
||||
|
||||
(setq bbdb-mail-user-agent 'mu4e-user-agent)
|
||||
(setq mu4e-view-rendered-hook 'bbdb-mua-auto-update)
|
||||
(setq mu4e-compose-complete-addresses nil)
|
||||
(setq bbdb-mua-pop-up t)
|
||||
(setq bbdb-mua-pop-up-window-size 5)
|
||||
(setq mu4e-view-show-addresses t)
|
||||
@end lisp
|
||||
|
||||
@noindent
|
||||
After this, you should be able to:
|
||||
@itemize
|
||||
@item In mu4e-view mode, add the sender of the email to BBDB with @key{C-u :}
|
||||
@item Tab-complete addresses from BBDB when composing emails
|
||||
@item View the BBDB contact while viewing a message
|
||||
@end itemize
|
||||
|
||||
|
||||
@node Sauron
|
||||
@section Sauron
|
||||
|
||||
|
@ -3377,40 +3483,6 @@ You might want to put:
|
|||
in your setup, to allow the script to find the D-Bus session bus, even when
|
||||
running outside its session.
|
||||
|
||||
@node Speedbar
|
||||
@section Speedbar
|
||||
|
||||
@code{speedbar} is an Emacs-extension that shows navigational
|
||||
information for an Emacs buffer in a separate frame. Using
|
||||
@code{mu4e-speedbar}, @t{mu4e} lists your bookmarks and maildir
|
||||
folders and allows for one-click access to them.
|
||||
|
||||
To enable this, add @t{(require 'mu4e-speedbar)} to your configuration;
|
||||
then, all you need to do to activate it is @kbd{M-x speedbar}. Then,
|
||||
when then switching to the @ref{Main view}, the speedbar-frame is
|
||||
updated with your bookmarks and maildirs.
|
||||
|
||||
For speed reasons, the list of maildirs is determined when @t{mu4e}
|
||||
starts; if the list of maildirs changes while @t{mu4e} is running, you
|
||||
need to restart @t{mu4e} to have those changes reflected in the speedbar
|
||||
and in other places that use this list, such as auto-completion when
|
||||
jumping to a maildir.
|
||||
|
||||
@node Dired
|
||||
@section Dired
|
||||
|
||||
It is possible to attach files to @t{mu4e} messages using @t{dired}
|
||||
(@ref{Dired,,emacs}), using the following steps (based on a post on
|
||||
the @t{mu-discuss} mailing list by @emph{Stephen Eglen}).
|
||||
|
||||
|
||||
@lisp
|
||||
(add-hook 'dired-mode-hook 'turn-on-gnus-dired-mode)
|
||||
@end lisp
|
||||
|
||||
Then, mark the file(s) in @t{dired} you would like to attach and press
|
||||
@t{C-c RET C-a}, and you'll be asked whether to attach them to an
|
||||
existing message, or create a new one.
|
||||
|
||||
@node Hydra
|
||||
@section Hydra
|
||||
|
@ -3439,8 +3511,8 @@ With Hydra installed, we can add multi-character shortcuts, for instance:
|
|||
Now, you can bind a convenient key to my-mu4e-bookmarks/body.
|
||||
@end lisp
|
||||
|
||||
@node Example configs
|
||||
@appendix Example configs
|
||||
@node Example configurations
|
||||
@appendix Example configurations
|
||||
|
||||
In this chapter, we show some example configurations. While it is very useful
|
||||
to see some working settings, we'd like to warn against blindly copying such
|
||||
|
@ -3511,7 +3583,7 @@ customize.
|
|||
mu4e-trash-folder "/trash")
|
||||
|
||||
;; the maildirs you use frequently; access them with 'j' ('jump')
|
||||
(setq mu4e-maildir-shortcuts
|
||||
(setq mu4e-maildir-shortcuts
|
||||
'((:maildir "/archive" :key ?a)
|
||||
(:maildir "/inbox" :key ?i)
|
||||
(:maildir "/work" :key ?w)
|
||||
|
@ -3527,6 +3599,10 @@ customize.
|
|||
(:from . 22)
|
||||
(:subject . nil))) ;; alternatively, use :thread-subject
|
||||
|
||||
(add-to-list 'mu4e-bookmarks
|
||||
;; ':favorite t' i.e, use this one for the modeline
|
||||
'(:query "maildir:/inbox" :name "Inbox" :key ?i :favorite t))
|
||||
|
||||
;; program to get mail; alternatives are 'fetchmail', 'getmail'
|
||||
;; isync or your own shellscript. called when 'U' is pressed in
|
||||
;; main view.
|
||||
|
@ -3688,6 +3764,10 @@ Next step: let's make a @t{mu4e} configuration for this:
|
|||
(:maildir "/[Gmail].Trash" :key ?t)
|
||||
(:maildir "/[Gmail].All Mail" :key ?a)))
|
||||
|
||||
(add-to-list 'mu4e-bookmarks
|
||||
;; ':favorite t' i.e, use this one for the modeline
|
||||
'(:query "maildir:/inbox" :name "Inbox" :key ?i :favorite t))
|
||||
|
||||
;; allow for updating mail using 'U' in the main view:
|
||||
(setq mu4e-get-mail-command "offlineimap")
|
||||
|
||||
|
@ -3801,7 +3881,7 @@ Yes you can --- see the documentation for the variable
|
|||
@t{mu4e-headers-leave-behavior}.
|
||||
|
||||
@subsection How can I set @t{mu4e} as the default e-mail client in Emacs?
|
||||
See @ref{Emacs default}.
|
||||
See @ref{Default email client}.
|
||||
|
||||
@subsection Can @t{mu4e} use some fancy Unicode instead of these boring plain-ASCII ones?
|
||||
Glad you asked! Yes, if you set @code{mu4e-use-fancy-chars} to @t{t},
|
||||
|
@ -4619,7 +4699,7 @@ to provide this information (this is implemented in
|
|||
@file{mu-cmd-server.c}).
|
||||
|
||||
We start this sequence when @t{mu4e} is invoked (when the program is
|
||||
started). It calls @t{mu4e-server-ping}, and registers a (lambda)
|
||||
started). It calls @t{mu4e--server-ping}, and registers a (lambda)
|
||||
function for @t{mu4e-server-pong-func}, to handle the response.
|
||||
|
||||
@verbatim
|
||||
|
@ -4667,9 +4747,9 @@ it on all the time. By default, the log only maintains the most recent
|
|||
@c @unnumbered Variable Index
|
||||
@c @printindex vr
|
||||
|
||||
@c @node Concept Index
|
||||
@c @unnumbered Concept Index
|
||||
@c @printindex cp
|
||||
@node Concept Index
|
||||
@unnumbered Concept Index
|
||||
@printindex cp
|
||||
|
||||
@bye
|
||||
|
||||
|
|
Loading…
Reference in New Issue