It was decided that auto-signing is potentially too troublesome for the
apparently common case of users who enable crypto processing for the
purpose of checking signature validity but who are not in a position to
sign out-going messages. Users can still manually invoke signing as needed.
Encrypting replies to encrypted messages is more of a security issue
so we leave it in place.
This is a simple approach to improving security when replying to
signed or encrypted messages. If the message being replied to was
signed, add mml tag to sign the reply. If the message being replied to
was encrypted, add mml tag to sign and encrypt the reply.
This may need configuration; I for one might want to encrypt replies
to encrypted messages, but not always sign replies to signed messages.
This still includes a slight bug: if any mml tags are added, they are
included in the region containing the quoted parts. Killing the region
will kill the mml tags too.
This adds a sort-order option to saved-searches, stores it in the
saved-search buttons (widgets), and uses the stored value when the
button is pressed.
Storing the sort-order in the widget was suggested by Jani in
id:4c3876274126985683e888641b29cf18142a5eb8.1391771337.git.jani@nikula.org.
Make the defcustom for notmuch-saved-searches use the new plist
format. It should still work with oldstyle saved-searches but will
write the newstyle form.
Add helper functions to for saved searches to ease the transition to
the new plist form while maintaining backwards compatibility. They
will be used in the next patch.
The notmuch cli program and emacs lisp versions may differ (especially
in remote usage). It helps to resolve problems if we can determine
the versions of notmuch cli and notmuch emacs mua separately.
The build process now creates notmuch-version.el from template file
by filling the version info to notmuch-emacs-version variable.
We push mark on reply so user can cut the quote. Push the mark before
signature, if any, instead of end of buffer so the signature is
preserved.
This is consistent with message-kill-to-signature.
So that users can easily organize their notmuch-specific configurations
to separate file and they don't have to have notmuch configurations in
*every* emacs installation they launch, especially if those need to
'(require notmuch) to make the configurations possible.
When (require 'notmuch) is added to ~/.emacs notmuch is loaded to every
instance of emacs although it may not be used in majority of
those instances.
When (autoload 'notmuch "notmuch" ...) is added to ~/.emacs notmuch
is loaded (only) when user invokes the notmuch function.
User may want to add other entrypoints to notmuch by adding more
autoloads -- the autoload instruction given should offer them clue how
to do so.
Previously, the term escaper used a blacklist of characters that
needed escaping. This blacklist turned out to be somewhat incomplete;
for example, it did not contain non-whitespace ASCII control
characters or Unicode "fancy quotes", both of which do require the
term to be escaped.
Switch to a whitelist of characters that are definitely safe to leave
unquoted. This fixes the broken test introduced by the previous
patch.
This uses the recent functionality to show the tag changes in the tree
buffer. Currently this is only used to show changes the tree buffer
makes itself: i.e., it does not make display any changes reflecting
tagging done by other notmuch-buffers.
This uses the recent functionality to show the tag changes in the
search buffer. Currently this is only used to show changes the search
buffer makes itself: i.e., it does not make display any changes
reflecting tagging done by other notmuch-buffers.
This allows (and requires) the original-tags to be passed along with
the current-tags to be passed to notmuch-tag-format-tags. This allows
the tag formatting to show added and deleted tags.By default a removed
tag is displayed with strike-through in red (if strike-through is not
available, eg on a terminal, inverse video is used instead) and an
added tag is displayed underlined in green.
If the caller does not wish to use the new feature it can pass
current-tags for both arguments and, at this point, we do exactly that
in the three callers of this function.
Note, we cannot tidily allow original-tags to be optional because we would
need to distinguish nil meaning "we are not specifying original-tags"
from nil meaning there were no original-tags (an empty list).
We use this in subsequent patches to make it clear when a message was
unread when you first loaded a show buffer (previously the unread tag
could be removed before a user realised that it had been unread).
The code adds into the existing tag formatting code. The user can
specify exactly how a tag should be displayed normally, when deleted,
or when added.
Since the formatting code matches regexps a user can match all deleted
tags with a ".*" in notmuch-tag-deleted-formats. For example setting
notmuch-tag-deleted-formats to '((".*" nil)) tells notmuch not to show
deleted tags at all.
All the variables are customizable; however, more complicated cases
like changing the face depending on the type of display will require
custom lisp.
Currently this overrides notmuch-tag-deleted-formats for the tests
setting it to '((".*" nil)) so that they get removed from the display
and, thus, all tests still pass.
Add customize options for deleted/added tag formats. These are not
used yet but will be later in the series.
We switch to using `notmuch-apply-face' rather than `propertize' in
the defcustom for faces so that the faces for deleted/added tags add
to the default face attributes for the tag.
We special case deleting the unread tag as that tag is a strong visual
cue and we don't need that cue when we are just saying it used to be
unread. Thus, we revert to the normal tag face with strikethough for
deleted unread tags.
We will re-use the customize option for format-tags for formattting
deleted tags to added tags in the next patch so split it into a
widget. There should be no functional change.
This modifies `notmuch-tag-format-tag' to treat the keys of
`notmuch-tag-formats' as (anchored) regexps, rather than literal
strings. This is clearly more flexible, as it allows for prefix
matching, defining a fallback format, etc. This may cause compatibility
problems if people have customized `notmuch-tag-formats' to match tags
that contain regexp specials, but this seems unlikely.
Regular expression matching has quite a performance hit over string
lookup, so this also introduces a simple cache from exact tags to
formatted strings. The number of unique tags is likely to be quite
small, so this cache should have a high hit rate. In addition to
eliminating the regexp lookup in the common case, this cache stores
fully formatted tags, eliminating the repeated evaluation of potentially
expensive, user-specified formatting code. This makes regexp lookup at
least as fast as assoc for unformatted tags (e.g., inbox) and *faster*
than the current code for formatted tags (e.g., unread):
inbox (usec) unread (usec)
assoc: 0.4 2.8
regexp: 3.2 7.2
regexp+caching: 0.4 0.4
(Though even at 7.2 usec, tag formatting is not our top bottleneck.)
This cache must be explicitly cleared to keep it coherent, so this adds
the appropriate clearing calls.
This combines our two face combining functions into one, easy to use
function with a much shorter name: `notmuch-apply-face'. This
function takes the full set of arguments that
`notmuch-combine-face-text-property' took, but takes them in a more
convenient order and provides smarter defaults that make the function
easy to use on both strings and buffers.
Currently notmuch-show-pipe-message runs the command in the working
directory of the *notmuch-pipe* buffer if it exists, and the current
buffer's working directory (which is inherited to the new
*notmuch-pipe* buffer) otherwise. This is all very surprising to the
user, and it's difficult to know or change where the command will be
run.
Always use the current show buffer's working directory for piping. The
user can check that with M-x pwd and change it with M-x cd. This is
consistent with notmuch-show-pipe-part.
`notmuch-mua-prompt-for-sender' is over-engineered and often wrong.
It attempts to detect when all identities have the same name and
specialize the prompt to just the email address part. However, to do
this it uses `mail-extract-address-components', which is meant for
displaying email addresses, not general-purpose parsing, and hence
performs many canonicalizations that can interfere with this use. For
example, configuring notmuch-identities to ("Austin
<austin@example.com>"), will cause `notmuch-mua-prompt-for-sender' to
lose the name part entirely and return " <austin@example.com>".
This patch rewrites `notmuch-mua-prompt-for-sender' to simply prompt
for a full identity when notmuch-identities is configured, or to
prompt for a sender address when it isn't.
The original code also did several strange things, like using `eval'
and specifying that this function was interactive. As a side-effect,
this patch fixes these problems. And it adds a docstring.
Since a newline starts a new query in batch mode, this causes
mysterious crashes in the emacs interface if saved searches contain
newlines. See the discussion at
id:87wqhcxb5j.fsf@maritornes.cs.unb.ca
In general newlines seem to be just whitespace to the xapian query
parser, so this should be mainly harmless.
When "notmuch config" is called with the name of an empty or
unconfigured setting, it prints nothing (not even a new line).
Previously, `notmuch-config-get' assumed it would always print a
newline. As a result, when `notmuch-config-get' was called with the
name of an empty of unconfigured setting, it would attempt to
(substring "" 0 -1) to strip the newline, which would fail with a
(args-out-of-range "" 0 -1) exception.
Fix this by only stripping the newline if there actually is one.
Previously, we used `message-forward' to build forwarded messages, but
this function is simply too high-level to be a good fit for some of
what we do.
First, since `message-forward' builds a full forward message buffer
given the message to forward, we have to duplicate much of the logic
in `notmuch-mua-mail' to patch the notmuch-y things into the built
buffer.
Second, `message-forward' constructs the From header from
user-full-name and user-mail-address. As a result, if we prompt the
user for an identity, we have to parse it into name and address
components, just to have it put back together by `message-forward'.
This process is not entirely loss-less because
`mail-extract-address-components' does a lot of canonicalization
(since it's intended for displaying addresses, not for parsing them).
To fix these problems, don't use `message-forward' at all.
`message-forward' itself is basically just a call to `message-mail'
and `message-forward-make-body'. Do this ourselves, but call
`notmuch-mua-mail' instead of `message-mail' so we can directly build
a notmuch-y message and control the From header.
This also fixes a bug that was a direct consequence of our use of
`mail-extract-address-components': if the user chose an identity that
had no name part (or the name part matched the mailbox), we would bind
user-full-name to nil, which would cause an exception in the bowels of
message-mode because user-full-name is expected to always be a string
(even if it's just "").
Previously, we updated .eldeps only if the file contents actually
needed to change. This was done to avoid unnecessary make restarts
(if the .eldeps rule changes the mtime of .eldeps, make has to restart
to collect the new dependencies). However, this meant that, after a
modification to any .el file that did not change dependencies, .eldeps
would always be out of date, so every make invocation would run the
.eldeps rule, which is both expensive because it starts up Emacs and
noisy. This was true even when there was nothing to do. E.g.,
$ make clean && make
...
$ touch emacs/notmuch-lib.el && make
...
$ make
Use "make V=1" to see the verbose compile lines.
EMACS emacs/.eldeps
make: Nothing to be done for `all'.
$ make
Use "make V=1" to see the verbose compile lines.
EMACS emacs/.eldeps
make: Nothing to be done for `all'.
Fix this by replacing .eldeps with two files with identical content.
One tracks the mtime of the dependency information and triggers the
Emacs call to rebuild dependencies only when it may be necessary. The
other tracks the content only; this rule over-triggers in the same way
the old rule did, but this rule is cheap and quiet.
Searching by Message-Id no longer works via the old mail-archive.com
API, though I have contacted them in hopes that they restore it to
prevent dead links. Anyway, the new API is cleaner.
Acked-by: Austin Clements <amdragon@MIT.EDU>
Imitated from "Enabling advice" in Emacs lisp manual...
ad-disable-advice by itself only changes the enable flag for a
piece of advice. To make the change take effect in the
advised definition, the advice needs to be activated again.
Previously tree did not use tag-format-tags: since tree wants to
distinguish matching messages from non-matching messages it is not a
perfect fit.
However, in preparation for allowing tag-changes to be shown (i.e.,
added or deleted tags to be indicated) it is convenient to make all
places displaying tags call the same routines.
We modify notmuch-tag-format-tags slightly so that it can take and
argument for the default characteristics of the face before the
special tag features are applied.
This also means that things like the star symbol for flagged messages
all work in tree.
This adds default faces for matching and non-matching messages. This
makes it easier for a user to do broad customization without having to
customize every field. It also fits more neatly with the next patch
which switches to using notmuch-tag-format-tags for tag formatting.
We set the field specific face customization to nil for all the fields
which use the message default face to make it clear to a user which
fields customizations are being used.
Previously the tags on each line in tree view were separarted by ", "
not just " ". This is different from show and search views.
This patch removes this comma. This is a large patch as essentially
every line of each of the expected outputs in the tree tests needs
updating.
Apart from aesthetic reasons this simplifies the switch to
notmuch-tag-format-tags in the next patch.
If we don't have emacs, disable targets that used EMACS while doing
the recipes of that target.
If we do have emacs, make install-emacs depend on *.elc files,
as making the target will attempt to install those.
Previously notmuch-tree-get-message-id always returned the id
including the prefix "id:". Modify the function to take an optional
`bare' argument saying to return the raw string.
This will be useful later and brings the function in line with
notmuch-show-get-message-id.
In emacs 24.3+ the stdout/stderr from externally displaying an
attachment gets inserted into the show buffer. This is caused by
changes in mm-display-external in mm-decode.el.
Ideally, we would put this output in the notmuch errors buffer but the
handler is called asynchronously so we don't know when the output will
appear. Thus if we put it straight into the errors buffer it could get
interleaved with other errors. Also we can't easily tell when we
have got all the error output so can't wait until the process is complete.
One solution would be to create a new buffer for the stderr of each
attachment viewed. Again, since we can't tell when the process has
finished, we can't close these buffers automatically so this will
leave lots of buffers around.
Thus we add a debug variable notmuch-show-attachment-debug: it this is
non-nil we create a new buffer for each viewer; if this variable is
nil we just use a temp buffer which means all error output is
discarded (this is the same behaviour as with emacs pre 24.3).
In current emacs (24.3) select-active-regions is set to t by
default. The reply insertion code sets the region to the quoted
message to make it easy to delete (kill-region or C-w). These two
things combine to put the quoted message in the primary selection.
This is not what the user wanted and is a privacy risk (accidental
pasting of the quoted message). We can avoid some of the problems
by let-binding select-active-regions to nil. This fixes if the
primary selection was previously in a non-emacs window but not if
it was in an emacs window. To avoid the problem in the latter case
we deactivate mark.
One key test (which fails under many simpler "fixes") is: open emacs
24.3 with notmuch, open 2 windows (viewing different notmuch buffers),
highlight some text in one, and then reply to a message in the
other. In many of my earlier attempts to fix this big this test fails.
Following a suggestion by Austin in id:20130915153642.GY1426@mit.edu
we use remap for the over-riding bindings in pick. This means that if
the user modifies the global keymap these modifications will happen in
the tree-view versions of them too.
[tree-view overrides these to do things like close the message pane
before doing the action, so the functionality is very close to the
original common keymap function.]
remaps are a rather unusual keymap consisting of "first key" 'remap
and then "second-key" the remapped-function. Thus we do the
documentation for it separately.
To support key remapping in emacs help we need to know the base keymap
when looking at the remapping. keep track of this while we recurse
down the sub-keymaps in help.
The actual documentation function notmuch-describe-keymap was getting
rather complicated so split out the code for a single key into its own
function notmuch-describe-key.
If the user (or a mode) overrides a keybinding from the common keymap
in one of the modes then both help lines appear in the help screen
even though only one of them is applicable.
Fix this by checking if we already have that key binding. We do this
by constructing an list of (key . docstring) pairs so it is easy to
check if we have already had that binding. Then the actual print help
routine changes these pairs into strings "key \t docstring"
The routines that construct the help page in notmuch-lib rely on
match-data being preserved across some fairly complicated code. This
is currently valid but will not be when this series is finished. Thus
place everything between the string-match and replace-match inside a
save-match-data.
A standard way to unset a key binding is local-unset-key which is equivalent to
(define-key (current-local-map) key nil)
Currently notmuch-help gives an error and fails if a user has done this.
To fix this we only add a help line if the binding is non-nil.
The functions referred to in the documentation for this variable were
replaced by the unified `notmuch-poll-and-refresh-this-buffer' in
21474f0e. Update the documentation to reflect the new function.
This fixes races in thread-local and global tagging in notmuch-search
(e.g., "+", "-", "a", "*", etc.). Previously, these would modify tags
of new messages that arrived after the search. Now they only operate
on the messages that were in the threads when the search was
performed. This prevents surprises like archiving messages that
arrived in a thread after the search results were shown.
This eliminates `notmuch-search-find-thread-id-region(-search)'
because these functions strongly encouraged racy usage.
This fixes the two broken tests added by the previous patch.
(Unfortunately, it's difficult to first demonstrate this problem with
a known-broken test because modern Linux kernels have argument length
limits in the megabytes, which makes Emacs really slow!)
This adds support for passing a string to write to notmuch's stdin to
`notmuch-call-notmuch-process' and `notmuch-call-notmuch-sexp'. Since
this makes both interfaces a little more complicated, it also unifies
their documentation better.
Previously, this was in notmuch.el, but all of the other notmuch call
wrappers were in notmuch-lib.el. Move `notmuch-call-notmuch-process'
to live with its friends. This happens to fix a missing dependency
from notmuch-tag.el, which required notmuch-lib, but not notmuch.
We want to load notmuch-tree when notmuch is loaded, so include it as
a require in notmuch.el. To avoid circular dependency we need to move
one keybinding from notmuch-tree.el to notmuch.el: it makes sense for
it to be defined there anyway.
Since tree is now loaded by default there is no need to print a
message when it is loaded.
notmuch-help is in notmuch.el not notmuch-lib.el and this is
incovenient for the way pick/tree uses it. I think lib makes more
sense anyway so move it there.
Previously, when a user fully completed a tag operation, they had to
press space to begin entering another tag operation. This is
different from, say, shell file name completion, which typically
inserts a space after an unambiguous completion under the assumption
that the user will want to enter more input.
This patch tweaks `notmuch-read-tag-changes' to act more like shell
file name completion: after an unambiguous tag completion, it now
inserts a space, ready and waiting for another tagging operation from
the user. This is backwards-compatible with old habits, since there's
no harm in putting an extra space.
Authors and subjects can contain embedded, encoded control characters
like "\n" and "\t" that mess up display. Transform control characters
into spaces everywhere we display them in search and show.
We no longer use this, since we've lifted all interactive behavior to
the appropriate interactive entry points. Because of this,
`notmuch-tag' also no longer needs to return the tag changes list,
since the caller always passes it in.
This is similar to the previous commit, but applies to search.
Search is somewhat more complicated because its tagging operations can
also apply to a region. Hence, this lifts interactive prompting into
a helper function. This also takes advantage of the new ability to
provide a prompt to distinguish tagging a single thread from tagging a
region of threads.
This modifies all tagging operations in show to call
`notmuch-read-tag-changes' in their interactive specification to input
tag changes, rather than depending on lower-level functions to prompt
for tag changes regardless of their calling context.
Besides being more Elispy and providing a more consistent programmatic
API, this enables callers to provide two call site-specific pieces of
information: an appropriate prompt, and the set of visible tags. The
prompt lets us differentiate * from +/-. Providing visible tags
enables a more consistent user experience than retrieving the
(potentially different) tags from the database, and avoids a
round-trip to the CLI and database.
This modifies the interface of `notmuch-read-tag-changes' to take an
optional prompt string as well as a list of existing tags instead of a
query. This list of tags is used to populate the tag removal
completions and lets the caller compute these in a more
efficient/consistent manner than performing a potentially large or
complex query. This patch also updates the sole current caller of
`notmuch-read-tag-changes'.
The calling convention for `notmuch-tag' changed in commit 97aa3c06 to
take a list of tag changes instead of a &rest argument, but the call
from `notmuch-search-tag-all' still passed a &rest argument. This
happened to work for interactive calls because tag-changes would be
nil, so the `apply' call would pass only the query string to
`notmuch-tag' and simply omit the &optional tag-changes argument.
Currently notmuch-show looks at the prefix-arg directly via
current-prefix-arg. This changes it to use the interactive
specification.
One test (for elide-toggle functionality) set the prefix arg
directly. Update this test to set the new argument directly.
Change foreground color to `blue' like lines representing threads
with flagged messages in notmuch-search. Before tag `flagged' was
shown in notmuch-show buffers as image star on graphical frames while
there was no visible distinction to other flags on terminal frames.
This improves the function documentation for many interactive
commands, either by improving their documentation string where the
improvement also makes sense for programmatic use or by adding a
'notmuch-doc property where it doesn't.
For nearly all commands that support a prefix argument, this adds a
'notmuch-prefix-doc property to document their prefixed behavior This
omits prefix documentation for a few commands where I thought the
prefixed behavior was too obscure (or too complex to fit in one line).
Traditionally, function documentation strings are intended primarily
for programmers, rather than users. They're written from the
perspective of calling the function, not interactively invoking it.
They're only ever displayed along with the function prototype (and
often refer to argument names). And built-in help commands like
`describe-bindings' show the name of the command, not its
documentation.
The notmuch help system is like `describe-bindings', but tries to be
more user-friendly by displaying documentation strings, rather than
Elisp command names. For most commands, this is fine, but for some
the "programmer description" is inappropriate for interactive use.
This is particularly noticeable for commands that take an optional
prefix argument.
This patch adds support for two symbol properties: notmuch-doc and
notmuch-prefix-doc, which let a command override its interactive
documentation and provide separate documentation for its prefixed
invocation. If notmuch-prefix-doc is present, we add an extra line to
the help giving the prefixed key sequence along with the documentation
for the prefixed command.
Like `notmuch-mua-new-forward-message', this is meant to be invoked
programmatically by something that can provide a reasonable query
string.
In fact, `notmuch-mua-new-reply's interactive specification didn't
match its arguments, so it wouldn't have worked interactively.
`notmuch-mua-new-forward-message' must be called from a buffer
containing a raw RFC2822-formatted message to forward. Hence, it's
intended to be invoked programmatically through something else that
sets up this buffer (like `notmuch-show-forward-message'), not
interactively.
Remove its interactive specification and update the documentation
string to mention the requirements on the current buffer.
In the recent changes for search order handling the default-value of
notmuch-search-oldest-first was used. However, default-value needs a
symbol so the symbol-name needs to be quoted.
This missing quote was causing strange sort-orders in some cases.
The only user-visible effect of this should be that "G" now works in
show mode (previously it was unbound for no apparent reason).
This shared keymap gives us one place to put global commands, which
both forces us to think about what commands should be global, and
ensures their bindings can't diverge (like the missing "G" in show).
This converts notmuch-help to use map-keymap for all keymap traversal.
This generally cleans up and simplifies construction of keymap
documentation, and also makes notmuch-help support anything that can
be in a keymap, including more esoteric stuff like multiple
inheritance.
This unifies the various refresh and poll-and-refresh functions we
have for different modes. Now all modes bind "=" and "G" (except
show, which doesn't bind "G" for some reason) to
`notmuch-refresh-this-buffer' and
`notmuch-poll-and-refresh-this-buffer', respectively.
Since notmuch-hello doesn't need this any more, we can remove this
hack. This also eliminates `notmuch-search-quit', so now all modes
bind "q" to `notmuch-kill-this-buffer'.
Since there is now no difference between notmuch-hello-search and
notmuch-search when called interactively, bind "s" to notmuch-search
in notmuch-hello-mode-map. Now all modes bind "s" this way.
Previously, we refreshed hello when the user quit a search that was
started from hello. This is fine assuming purely stack-oriented
buffer use, but is quite fragile and requires hacks to search.
This replaces that logic with a new approach that refreshes hello
whenever the user switches to the hello buffer, regardless of how this
happens.
Previously, if `notmuch-search' was called interactively (bound to "s"
in search and show, but not hello), it would always use newest-first.
However, `notmuch-hello-search' (bound to "s" in hello) and
`notmuch-hello-widget-search` would call it with the user-configured
sort order. This inconsistency seems unintentional, so change
`notmuch-search' to use the user-configured sort order when called
interactively.
When text/html parts include images as multipart/related and the
text/plain alternative is used these images can be completely hidden
with no easy way to access them or even find out that they are there.
Make notmuch-show-insert-part-multipart/related add buttons for all
parts, the first one visible the rest hidden.
The lazy part handler had a bug that it allowed the button to be
toggled to be specified. During toggling it needs to save and restore
the text-properties for the button but it actually saved the text
properties at point rather than from the button.
In almost all cases this didn't matter as as point had the same text
properties as the button. However, it is a bug and did cause incorrect
behaviour in some cases: see id:87txhz14z6.fsf@qmul.ac.uk for details.
When composing a reply, notmuch-mua-reply attempts to cite the
the original message by inserting it before the user signature, if
one is present. The existing method used to search the signature
separator backward from the end of the buffer and then move one
line up. In case of variable `message-signature-insert-empty-line'
being nil this caused point to go to the beginning of
'--text follows this line--'
separator line, and citation was inserted there.
This change checks the value of `message-signature-insert-empty-line'
and doesn't move point if that is nil. Additional narrowing to
the body region ensures that point never goes to the separator line
(or beyond).
`message-signature-setup-hook' or `message-setup-hook' may already have
added some other content to the message body, therefore using simply
(message-goto-body) to move point to the beginning of body might lead
to unexpected results.
Original patch from "Geoffrey H. Ferrari", continued with iterations
from Jani and Mark.
In reply, insert quotable parts using notmuch-show-insert-bodypart
instead of calling notmuch-mm-display-part-inline directly to render
the quoted parts as they are rendered in show view.
We use a temp buffer to not leak text properties from the show
renderer into the reply. This way we also don't need to worry about
narrowing or point placement. Credits to Mark Walters
<markwalters1009@gmail.com> and Austin Clements <amdragon@MIT.EDU> for
getting this part straight.
The notable change is that replies to text/calendar parts quote the
pretty printed output of icalendar-import-buffer rather than the ugly
raw vcalendar.
notmuch-show.el and notmuch.el had 3 duplicate, identical functions:
notmuch-foreach-mime-part, notmuch-count-attachments and
notmuch-save-attachments. Now these functions in notmuch-show.el
are replaced with declare-functions pointing to "notmuch"(.el).
Notmuch puts attachments in as declared content-type except when the
content-type is application/octet-stream it tries to guess the type
from the filename/extension. This means that viewing a pdf (for
example) which is sent as application/octet-strem invokes the pdf
viewer rather than just offering to save the part.
Recent changes to the attachment handling (commit 1546387d) changed
(broke) this. This patch stores the calculated mime-type with the part
and changes the attachment part handlers can use it instead.
Recently notmuch-hello was converted to use batch count. However, it
seems that several people run different versions of notmuch-emacs and
notmuch-cli so this batch makes emacs fail with an error message if
--batch is not available in the CLI.
Amended by: db
Notmuch cli provides all structured data previously provided
in json format now in s-expression format, rendering all current
json functionality obsolete.
This switches `notmuch-mua-reply' and `notmuch-query-get-threads' to
the S-exp format. These were the last two uses of the JSON format in
the Emacs frontend.
This is just like `notmuch-call-notmuch-json', but parses S-expression
output. Note that, also like `notmuch-call-notmuch-json', this
doesn't consider trailing data to be an error, which may or may not be
what we want in the long run.
This removes the v command, since we now have much nicer part commands,
and deprecates the underlying notmuch-show-view-all-mime-parts. This
also means that people who try using the old unprefixed 'v' command on
a part button will no longer be greeted by ALL of their parts popping
up.
Previously the query string for piping a message to a command was
"Pipe message to command: " regardless of whether the function was
called with a prefix argument (which pipes all open messages to the
command). This patch modifies the `interactive' command to reflect
this.
This adds the actual code to do the lazy insertion of hidden parts.
We use a memory inefficient but simple method: when we come to insert
the part if it is hidden we just store all of the arguments to the
part insertion function as a button property. This means when we want
to show the part we can just resume where we left off.
One thing is that we can't tell if a lazy part will produce text until
we try to render it so when unhiding a part we check to see if it
rendered; if not we invoke the default part handler (e.g. an external
viewer).
Also, we would like to insert the lazy part at the start of the line
after the part button. But if this line has some text properties
(e.g. the colours for a following message header) then the lazy part
gets these properties. Thus we start at the end of the part button
line, insert a newline, insert the lazy part, and then delete the
extra newline at the end of the part.
Previously, whether a part was hidden or shown was recorded in the
invisibility/visibility of the part overlay. Since we are going to
have lazily rendered parts with no overlay store the hidden/shown
state in the part button itself.
Additionally, in preparation for the invisible part handling move the
actual hiding of the hidden parts to insert-bodypart from
create-part-overlays.
Finally, we will need to know whether a part-insertion has done
anything (it won't if the invisible part cannot be displayed by emacs)
so we slightly rejig the code order in
notmuch-show-toggle-part-invisibility to make it easier for the
function to set an appropriate return value.
Previously each of the part insertion handlers inserted the part
button themselves. Move this up into
notmuch-show-insert-bodypart. Since a small number of the handlers
modify the button (the encryption/signature ones) we need to pass the
header button as an argument into the individual part insertion
handlers. However, the declared-type argument was only used for the
text for the part buttons we can now omit it.
The patch is large but mostly simple. The only things of note are that
we let the text/plain handler applies notmuch-wash to the whole part
including the part button. In particular, notmuch-wash removes leading
blank lines from a text/plain part, but since the button is counted as
part of the part this does not happen with text/plain buttons that
have a button. This is probably a bug in notmuch-wash but changing it
does make several tests fail (that rely on this blank line) so, for
the moment, keep the old behaviour.
Earlier patches have moved the handling of wash fake inline patch
parts to insert-bodypart so we can drop the function
notmuch-show-insert-part-inline-patch-fake-part
Occasionally, when the user killed the search buffer when the CLI
process was still running, Emacs would run the
notmuch-start-notmuch-sentinel sentinel twice. The first call would
process and delete the error output file and the second would fail
with an "Opening input file: no such file or directory, ..." error
when attempting to access the error file.
Emacs isn't supposed to run the sentinel twice. The reason it does is
rather subtle (and probably a bug in Emacs):
1) When the user kills the search buffer, Emacs invokes
kill_buffer_processes, which sends a SIGHUP to notmuch, but doesn't do
anything else. Meanwhile, suppose the notmuch search process has
printed some more output, but Emacs hasn't consumed it yet (this is
critical and is why this error only happens sometimes).
2) Emacs gets a SIGCHLD from the dying notmuch process, which invokes
handle_child_signal, which sets the new process status, but can't do
anything else because it's a signal handler.
3) Emacs returns to its idle loop, which calls status_notify, which
sees that the notmuch process has a new status. This is where things
get interesting.
3.1) Emacs guarantees that it will run process filters on any
unconsumed output before running the process sentinel, so
status_notify calls read_process_output, which consumes the final
output and calls notmuch-search-process-filter.
3.1.1) notmuch-search-process-filter checks if the search buffer is
still alive and, since it's not, it calls delete-process.
3.1.1.1) delete-process correctly sees that the process is already
dead and doesn't try to send another signal, *but* it still modifies
the status to "killed". To deal with the new status, it calls
status_notify. Dun dun dun. We've seen this function before.
3.1.1.1.1) The *recursive* status_notify invocation sees that the
process has a new status and doesn't have any more output to consume,
so it invokes our sentinel and returns.
3.2) The outer status_notify call (which we're still in) is now done
flushing pending process output, so it *also* invokes our sentinel.
This patch addresses this problem at step 3.1.1, where the filter
calls delete-process, since this is a strange and redundant thing to
do anyway.
Previously, when the user killed the search buffer before the CLI
search process had completed, we would report the signal sent by Emacs
to kill the CLI to the user as an error. Fix this by only reporting
error exits if the process buffer is still live. We still report
stderr output regardless in case stderr output was relevant to why the
user killed the search buffer (such as a wrapper script being stuck).
This commit adds an extra button at the end of the search entries that
allows deleting that individual search from the history. A short
confirmation («y» or «n») is made before taking action.
The button to clear the recent searches in notmuch-hello is easy to
press accidentally while moving around the, clearing potentially
useful searches with no way of recovering them.
Previously, we simply called pushnew to add :notmuch-part to the
front-sticky and rear-nonsticky text property lists. This works if
these are nil or lists, but they can also have the value t, meaning
that all properties are front-sticky/rear-nonsticky. In this case,
pushnew will signal an error because t is not a list. We never set
these properties to t ourselves, but since we apply these property
changes over arbitrary renderer output, we have to deal with this
possibility.
Several function docstrings refer to behaviour in docstrings that is
really controlled by notmuch-archive-tags. Add cross references, and
replace hardcoding.
These functions refer to default values of variables, but it seems
less confusing and less likely to get out of date to just allow the
user to follow the help cross-reference links.
I found several places where a setq is immediately followed by a let
or a let*. This seems to be the pessimal combination, with the
implicit scope of the setq combined with the extra indentation of the let.
I combined these cases into a single let* which I think is easier to read.
I can't see any benefit to the funcall, and it looks like the result
of cut-and-paste from some code that actually used a variable for the
function to call.
In addition to being the Right Thing to do, this noticeably improves
the time taken to display the first page of search results, since it's
roughly an order of magnitude faster than the JSON parser.
Interestingly, it does *not* significantly improve the time to
completely fill a large search buffer because for large search
buffers, the cost of creating author invisibility overlays and
inserting text (which slows down with more overlays) dominates.
However, the time required to display the first page of results is
generally more important to the user experience.
This provides the same interface as the streaming JSON parser, but
reads S-expressions incrementally. The only difference is that the
`notmuch-sexp-parse-partial-list' helper does not handle interleaved
error messages (since we now have the ability to separate these out at
the invocation level), so it no longer takes an error function and
does not need to do the horrible resynchronization that the JSON
parser had to.
Some implementation improvements have been made over the JSON parser.
This uses a vector instead of a list for the parser data structure,
since this allows faster access to elements (and modern versions of
Emacs handle storage of small vectors efficiently). Private functions
follow the "prefix--name" convention. And the implementation is much
simpler overall because S-expressions are much easier to parse.
Previously, search started the async notmuch process directly. Now,
it uses `notmuch-start-notmuch'. This simplifies the process sentinel
a bit and means that we no longer have to worry about errors
interleaved with the JSON output.
We also update the tests of Emacs error handling, since the error
output is now separated from the search results buffer.
This provides a new notmuch-lib utility to start an asynchronous
notmuch process that handles redirecting of stderr and checking of the
exit status. This is similar to `notmuch-call-notmuch-json', but for
asynchronous processes (and it leaves output processing to the
caller).
Since the part commands are no longer tied to a button, but can be
applied with point anywhere within a part, bind the part commands
keymap to "." everywhere in the show buffer. This lets you save or
view parts without having to navigate to the part button, and is
particularly useful for parts that have no button.
This removes the un-prefixed MIME part commands from the part button
keymap, but that's okay because those clashed in annoying ways with
show buffer bindings like "s" for search. RET on part buttons is
unaffected, which is the most important part button binding.
This unifies the part button actions and the underlying part action
functions into single interactive command that simply applies to the
part containing point using the just-added part p-list text property
instead of button properties. Since all part actions can be performed
by applying the appropriate mm function to an mm-handle, this patch
abstracts out the creation of mm handles, making the implementations
of the part commands trivial. This also eliminates our special
handling for part save in favor of using the appropriate mm function.
This necessarily modifies the way we handle the default part button
action, but in a way that does not change the meaning of the
notmuch-show-part-button-default-action defcustom.
Since these commands are no longer specific to buttons, this patch
eliminates the extra metadata stored with each button. This also
eliminates one rather special-purpose macro for a collection of
general purpose part handling utilities.
This is similar to what we already do with the message p-list, though
we apply the part's text property to the whole part's text, in
contrast with the message p-list, which is (rather obscurely) only
applied to the first character.
Previously, we lost any text properties applied to part buttons or
wash buttons when they were toggled because `insert' directly copies
the text properties of the string being inserted. Fix this by
capturing the properties applied to the button beforehand and
re-applying them after inserting the new text.
For such a simple regexp, this was broken in a very complicated way.
The intent was to strip the newline (and potentially other whitespace)
off the end of the error string so there wasn't an extra newline in
the error signal. However, the regexp was deeply dependent on the
active syntax table and the subtleties of $. We didn't notice this
because all notmuch major modes put ?\n in the whitespace class, which
makes this behaved as intended: the "\\s " matches all newlines, but
by matching the newline character, causes the $ *not* to match
*except* where it matched the empty string at the very end of the
string, which was not followed by a newline.
However, if the syntax table declares ?\n to be non-whitespace
(lisp-mode declares it as endcomment, and is likely to be the mode
you're in when testing functions), then this regexp behaves completely
differently, matching trailing spaces at the end of every line within
the string.
The solution is to say what we mean for whitespace *and* to switch
from $ to \', which matches only the end of the string, rather than
the end of each line. Both are necessary or this will strip away
interior newlines, which is not what we want.
Previously, notmuch-show-view-part overrode the function binding of
mm-show-part to redirect it to notmuch-show-save-part to get notmuch's
default file name handling in case mm-display-part decided to fall
back to saving the part. In addition to being messy, this depended on
the now-deprecated dynamic binding behavior of flet.
This patch removes the mm-show-part override in favor of passing the
file name in to mm-show-part the way it expects, so we get its default
file name handling. It's not clear why we didn't do this before;
mm-show-part has supported default file names since at least Emacs
23.1.
Previously, we simply byte compiled each Elisp source file
independently. This is actually the wrong thing to do and can lead to
issues with macros and performance issues with substitutions because
1) when the byte compiler encounters a (require 'x) form, it will load
x.elc in preference to x.el, even if x.el is newer, and as a result
may load old macro and substitution definitions and 2) if we update a
macro or substitution definition in one file, we currently won't
re-compile other files that depend on the file containing the
definition.
This patch addresses these problems by computing make dependency rules
from the (require 'x) forms in the Elisp source files, which we inject
into make's dependency database.
Currently mime parts are basically handled based on their mime-type
with the exception of application/octet-stream parts. Deal with these
parts at the top level (notmuch-show-insert-bodypart).
This is needed later in the series as we need to put in a part button
for each part (which means knowing its mime type) while deferring the
actual insertion of the part.
Apparently Emacs provides a function to stringify errors properly.
Use this in the search sentinel where we have to do our own error
messaging, rather than assuming the first error argument will be the
descriptive string.
When compiling notmuch-tag.el there is a compile warning:
notmuch-tag.el:27:1:Warning: cl package required at runtime
Since we have decided to allow runtime use of cl we suppress this
warning by adding a tail comment to the file.
The support for emacs version 22 has not worked at least since
September 2011 when I attempted to use it. I expanded the support in
id:yf6ippgtbn0.fsf@taco2.nixu.fi but that was not enough and then I
found it easier to switch to emacs 23.
In case one wants to resurrect emacs 22 (or earlier!) support, pick
the changes from the patch email referenced above.
Added a customizable variable notmuch-address-selection-function
and the function with the same name to provide a way for user to
change the function called to do address selection.
By default the functionality is exactly the same as it has been so
far; completing-read is called with the same parameters as before.
Setting equivalent lambda expression in place of using
notmuch-address-selection-function function is done as follows:
(setq notmuch-address-selection-function
(lambda (prompt collection initial-input)
(completing-read prompt collection nil nil initial-input)))
For example drop-in replacement with ido-completing-read can be done
easily as an one alternative to the default.
Some (declare-function ...) definitions were drifted away from the
actual (defun ...)'s. To find the drifts and to verify changes
the following command line was used:
$ emacs --batch -L emacs --eval '(check-declare-directory "emacs")'
From a show buffer, notmuch-bbdb/snarf-from imports the sender into
bbdb. notmuch-bbdb/snarf-to imports all recipients. Newly imported
contacts are reported in the minibuffer / Messages buffer.
Both functions use the BBDB parser to recognize email address formats.
This modifies notmuch hello to use the new count --batch
functionality. It should give exactly the same results as before but
under many conditions it should be much faster. In particular it is
much faster for remote use.
The code is a little ugly as it has to do some working out of the
query when asking the query and some when dealing with the result.
However, the code path is exactly the same in both local and remote
use.
This has two benefits: unified error handling, and avoiding tramp's
hooking into shell-command-string.
This seems to be a fix for id:874nguxbvq.fsf@tu-dortmund.de
This patch extracts the rendering of tags in notmuch-show to
the notmuch-tag file.
This file introduces a `notmuch-tag-formats' variable that associates
each tag to a particular format. This variable can be customized
thanks to the work of Austin Clements. For example,
'(("unread" (propertize tag 'face '(:foreground "red")))
("flagged" (notmuch-tag-format-image tag "star.svg")))
associates a red foreground to the "unread" tag and a star picture to
the "flagged" tag.
Signed-off-by: Damien Cassou <damien.cassou@gmail.com>
This improves notmuch-combine-face-text-property to support both
applying faces to strings and to support combining the given face
under existing faces, rather than over.
Previously, notmuch-combine-face-text-property assumed that any
existing face properties of the modified text were already in face
list form. This was true as long as it was the only function
manipulating faces (since it always produced a list form face), but if
anything else has manipulated the face, it was more likely to be
either a face name or a face plist. It also didn't correctly handle
face lists as arguments, even though the doc string claimed it did.
This patch fixes notmuch-combine-face-text-property to handle all face
forms correctly by canonicalizing both the argument face and the
existing faces into list form. This also means we can set the face to
a simpler non-list form if there's no existing face.
Emacs has two button type objects: widgets (as used for saved searches
in notmuch-hello) and buttons as used by parts/citations and id links
in notmuch-show. These two behave subtly differently when clicked with
the mouse: widgets select the window clicked before running the
action, buttons do not.
This patch makes all of these behave the same: clicking always selects
the clicked window. It does this by defining a notmuch-button-type
supertype that the other notmuch buttons can inherit from. This
supertype binds the mouse-action to select the window and then
activate the button.
There is a bug in the current notmuch code with w3m and invisible
parts. w3m sets a keymap, and if we have a hidden [text/html] point
at the start of the following line still gets this w3m keymap which
causes some strange effects. For example, RET gives an error "No URL
at Point" rather than hiding the message, <down> goes to the next link
rather than just down a line.
These keybinding are also inconvenient when the text/html part is
displayed so we ask w3m not to install a keymap.
This is only likely to be a problem for emacs 23 as shr is preferred
as html renderer on emacs 24 (although the user can set the renderer
to w3m even on emacs 24).
This solution was suggested by Tomi Ollila <tomi.ollila@iki.fi>
We recently switched to popping up a buffer to report CLI errors, but
this was too intrusive, especially for transient errors and especially
since we made fewer things ignore errors. This patch changes this to
display a basic error message in the minibuffer (using Emacs' usual
error handling path) and, if there are additional details, to log
these to a separate error buffer and reference the error buffer from
the minibuffer message. This is more in line with how Emacs typically
handles errors, but makes the details available to the user without
flooding them with the details.
Given this split, we pare down the basic message and make it more
user-friendly, and also make the verbose message even more detailed
(and more debugging-oriented).