[PATCH v2 5/5] News for Emacs part handling changes
--- NEWS | 16 1 file changed, 16 insertions(+) diff --git a/NEWS b/NEWS index a7f2ec6..23f4c6a 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision. Emacs Interface --- +New keymap to view/save parts + + To view or save a single MIME part of a message, use the new "." + submap (e.g., ". s" to save, ". v" to view). Previously, these keys + were only available when point was on a part button and they did not + have the "." prefix, so they were difficult to invoke (impossible if + a part did not have a button) and clashed with other bindings. + These new bindings also appear in show's help, so you don't have to + memorize them. + +Default part save directory is now `mm-default-directory` + + Previously, notmuch offered to save parts and attachments to a mix + of `mm-default-directory`, `mailcap-download-directory`, and `~/`. + This has been standardized on `mm-default-directory`. + No Emacs 22 support The Emacs 22 support added late 2010 was sufficient only for a short -- 1.7.10.4
[PATCH v2 4/5] emacs: Bind MIME part commands to "." submap
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. --- emacs/notmuch-show.el | 23 +++ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 0d9a34c..613e666 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -466,22 +466,10 @@ message at DEPTH in the current thread." (define-button-type 'notmuch-show-part-button-type 'action 'notmuch-show-part-button-default - 'keymap 'notmuch-show-part-button-map 'follow-link t 'face 'message-mml :supertype 'notmuch-button-type) -(defvar notmuch-show-part-button-map - (let ((map (make-sparse-keymap))) -(set-keymap-parent map button-map) -(define-key map "s" 'notmuch-show-save-part) -(define-key map "v" 'notmuch-show-view-part) -(define-key map "o" 'notmuch-show-interactively-view-part) -(define-key map "|" 'notmuch-show-pipe-part) -map) - "Submap for button commands") -(fset 'notmuch-show-part-button-map notmuch-show-part-button-map) - (defun notmuch-show-insert-part-header (nth content-type declared-type name comment) (let ((button) (base-label (concat (when name (concat name ": ")) @@ -1202,6 +1190,16 @@ reset based on the original query." "Submap for stash commands") (fset 'notmuch-show-stash-map notmuch-show-stash-map) +(defvar notmuch-show-part-map + (let ((map (make-sparse-keymap))) +(define-key map "s" 'notmuch-show-save-part) +(define-key map "v" 'notmuch-show-view-part) +(define-key map "o" 'notmuch-show-interactively-view-part) +(define-key map "|" 'notmuch-show-pipe-part) +map) + "Submap for part commands") +(fset 'notmuch-show-part-map notmuch-show-part-map) + (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) (define-key map "?" 'notmuch-help) @@ -1244,6 +1242,7 @@ reset based on the original query." (define-key map "$" 'notmuch-show-toggle-process-crypto) (define-key map "<" 'notmuch-show-toggle-thread-indentation) (define-key map "t" 'toggle-truncate-lines) + (define-key map "." 'notmuch-show-part-map) map) "Keymap for \"notmuch show\" buffers.") (fset 'notmuch-show-mode-map notmuch-show-mode-map) -- 1.7.10.4
[PATCH v2 3/5] emacs: Simplify MIME part command implementation
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. --- emacs/notmuch-show.el | 133 + test/emacs|4 +- 2 files changed, 61 insertions(+), 76 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index e84e1ba..0d9a34c 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -474,10 +474,10 @@ message at DEPTH in the current thread." (defvar notmuch-show-part-button-map (let ((map (make-sparse-keymap))) (set-keymap-parent map button-map) -(define-key map "s" 'notmuch-show-part-button-save) -(define-key map "v" 'notmuch-show-part-button-view) -(define-key map "o" 'notmuch-show-part-button-interactively-view) -(define-key map "|" 'notmuch-show-part-button-pipe) +(define-key map "s" 'notmuch-show-save-part) +(define-key map "v" 'notmuch-show-view-part) +(define-key map "o" 'notmuch-show-interactively-view-part) +(define-key map "|" 'notmuch-show-pipe-part) map) "Submap for button commands") (fset 'notmuch-show-part-button-map notmuch-show-part-button-map) @@ -494,61 +494,11 @@ message at DEPTH in the current thread." (insert-button (concat "[ " base-label " ]") :base-label base-label - :type 'notmuch-show-part-button-type - :notmuch-part nth - :notmuch-filename name - :notmuch-content-type content-type)) + :type 'notmuch-show-part-button-type)) (insert "\n") ;; return button button)) -;; Functions handling particular MIME parts. - -(defmacro notmuch-with-temp-part-buffer (message-id nth body) - (declare (indent 2)) - (let ((process-crypto (make-symbol "process-crypto"))) -`(let ((,process-crypto notmuch-show-process-crypto)) - (with-temp-buffer -(setq notmuch-show-process-crypto ,process-crypto) -;; Always acquires the part via `notmuch part', even if it is -;; available in the JSON output. -(insert (notmuch-get-bodypart-internal ,message-id ,nth notmuch-show-process-crypto)) -, at body - -(defun notmuch-show-save-part (message-id nth filename content-type) - (notmuch-with-temp-part-buffer message-id nth -(let ((file (read-file-name -"Filename to save as: " -(or mailcap-download-directory "~/") -nil nil -filename))) - ;; Don't re-compress .gz & al. Arguably we should make - ;; `file-name-handler-alist' nil, but that would chop - ;; ange-ftp, which is reasonable to use here. - (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t - -(defun notmuch-show-view-part (message-id nth filename content-type ) - (notmuch-with-temp-part-buffer message-id nth -(let* ((disposition (if filename `(attachment (filename . ,filename - (handle (mm-make-handle (current-buffer) (list content-type) - nil nil disposition)) - ;; Set the default save directory to be consistent with - ;; `notmuch-show-save-part'. - (mm-default-directory (or mailcap-download-directory "~/")) - ;; set mm-inlined-types to nil to force an external viewer - (mm-inlined-types nil)) - (mm-display-part handle - -(defun notmuch-show-interactively-view-part (message-id nth filename content-type) - (notmuch-with-temp-part-buffer message-id nth -(let ((handle (mm-make-handle (current-buffer) (list content-type - (mm-interactively-view-part handle - -(defun notmuch-show-pipe-part (message-id nth filename content-type) - (notmuch-with-temp-part-buffer message-id nth -(let ((handle (mm-make-handle (current-buffer) (list content-type - (mm-pipe-part handle - ;; This is taken from notmuch-wash: maybe it should be unified? (defun notmuch-show-toggle-part-invisibility ( button) (interactive) @@ -570,6 +520,8 @@ message at DEPTH in the current thread." (delete-region (point) old-end)) (goto-char (min
[PATCH v2 2/5] emacs: Record part p-list in a text property
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. --- emacs/notmuch-lib.el | 12 emacs/notmuch-show.el | 20 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 790136e..2186783 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -360,6 +360,18 @@ OBJECT." below string)) +(defun notmuch-map-text-property (start end prop func object) + "Transform text property PROP using FUNC. + +Applies FUNC to each distinct value of the text property PROP +between START and END of OBJECT, setting PROP to the value +returned by FUNC." + (while (< start end) +(let ((value (get-text-property start prop object)) + (next (next-single-property-change start prop object end))) + (put-text-property start next prop (funcall func value) object) + (setq start next + (defun notmuch-logged-error (msg extra) "Log MSG and EXTRA to *Notmuch errors* and signal MSG. diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index a080134..e84e1ba 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -900,7 +900,17 @@ If HIDE is non-nil then initially hide this part." ;; Ensure that the part ends with a carriage return. (unless (bolp) (insert "\n")) -(notmuch-show-create-part-overlays msg beg (point) hide))) +(notmuch-show-create-part-overlays msg beg (point) hide) +;; Record part information. Since we already inserted subparts, +;; don't override existing :notmuch-part properties. +(notmuch-map-text-property beg (point) :notmuch-part + (lambda (v) (or v part))) +;; Make :notmuch-part front sticky and rear non-sticky so it stays +;; applied to the beginning of each line when we indent the message. +(notmuch-map-text-property beg (point) 'front-sticky + (lambda (v) (pushnew :notmuch-part v))) +(notmuch-map-text-property beg (point) 'rear-nonsticky + (lambda (v) (pushnew :notmuch-part v) (defun notmuch-show-insert-body (msg body depth) "Insert the body BODY at depth DEPTH in the current thread." @@ -1404,6 +1414,14 @@ Some useful entries are: (notmuch-show-move-to-message-top) (get-text-property (point) :notmuch-message-properties))) +(defun notmuch-show-get-part-properties () + "Return the properties of the innermost part containing point. + +This is the part property list retrieved from the CLI. Signals +an error if there is no part containing point." + (or (get-text-property (point) :notmuch-part) + (error "No message part here"))) + (defun notmuch-show-set-prop (prop val props) (let ((inhibit-read-only t) (props (or props -- 1.7.10.4
[PATCH v2 1/5] emacs: Retain text properties when toggling buttons
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. --- emacs/notmuch-show.el |2 ++ emacs/notmuch-wash.el |2 ++ 2 files changed, 4 insertions(+) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index b0a8d8a..a080134 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -559,10 +559,12 @@ message at DEPTH in the current thread." (new-start (button-start button)) (button-label (button-get button :base-label)) (old-point (point)) +(properties (text-properties-at (point))) (inhibit-read-only t)) (overlay-put overlay 'invisible (not show)) (goto-char new-start) (insert "[ " button-label (if show " ]" " (hidden) ]")) + (set-text-properties new-start (point) properties) (let ((old-end (button-end button))) (move-overlay button new-start (point)) (delete-region (point) old-end)) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 8a68819..8fe91e1 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -104,9 +104,11 @@ lower).") (overlay (button-get cite-button 'overlay)) (button-label (notmuch-wash-button-label overlay)) (old-point (point)) +(properties (text-properties-at (point))) (inhibit-read-only t)) (goto-char new-start) (insert button-label) +(set-text-properties new-start (point) properties) (let ((old-end (button-end cite-button))) (move-overlay cite-button new-start (point)) (delete-region (point) old-end)) -- 1.7.10.4
[PATCH v2 0/5] emacs: Part command improvements
This is v2 of id:87zjvghx82.fsf at qmul.ac.uk. In addition to some general improvements, this fixes the handling of part overlays in indented messages, removes the special part button map entirely in favor of the "." submap, and adds a NEWS patch. The diff from v1 follows diff --git a/NEWS b/NEWS index a7f2ec6..23f4c6a 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision. Emacs Interface --- +New keymap to view/save parts + + To view or save a single MIME part of a message, use the new "." + submap (e.g., ". s" to save, ". v" to view). Previously, these keys + were only available when point was on a part button and they did not + have the "." prefix, so they were difficult to invoke (impossible if + a part did not have a button) and clashed with other bindings. + These new bindings also appear in show's help, so you don't have to + memorize them. + +Default part save directory is now `mm-default-directory` + + Previously, notmuch offered to save parts and attachments to a mix + of `mm-default-directory`, `mailcap-download-directory`, and `~/`. + This has been standardized on `mm-default-directory`. + No Emacs 22 support The Emacs 22 support added late 2010 was sufficient only for a short diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 09ce25e..2186783 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -360,21 +360,17 @@ OBJECT." below string)) -(defun notmuch-put-text-property-if-nil (start end property value - object) - "Like `put-text-property', but only set the property where it is nil." +(defun notmuch-map-text-property (start end prop func object) + "Transform text property PROP using FUNC. + +Applies FUNC to each distinct value of the text property PROP +between START and END of OBJECT, setting PROP to the value +returned by FUNC." (while (< start end) -(let ((start-nil (text-property-any start end property nil object))) - (if (null start-nil) - ;; There are no more nil regions; exit the loop - (setq start end) - ;; Find the end of the nil region - (let ((end-nil - (or (text-property-not-all start-nil end property nil object) - end))) - ;; Set the property - (put-text-property start-nil end-nil property value object) - (setq start end-nil)) +(let ((value (get-text-property start prop object)) + (next (next-single-property-change start prop object end))) + (put-text-property start next prop (funcall func value) object) + (setq start next (defun notmuch-logged-error (msg extra) "Log MSG and EXTRA to *Notmuch errors* and signal MSG. diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 380b144..613e666 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -466,7 +466,6 @@ message at DEPTH in the current thread." (define-button-type 'notmuch-show-part-button-type 'action 'notmuch-show-part-button-default - 'keymap 'notmuch-show-part-button-map 'follow-link t 'face 'message-mml :supertype 'notmuch-button-type) @@ -843,8 +842,15 @@ If HIDE is non-nil then initially hide this part." (insert "\n")) (notmuch-show-create-part-overlays msg beg (point) hide) ;; Record part information. Since we already inserted subparts, -;; don't override exiting :notmuch-part properties. -(notmuch-put-text-property-if-nil beg (point) :notmuch-part part))) +;; don't override existing :notmuch-part properties. +(notmuch-map-text-property beg (point) :notmuch-part + (lambda (v) (or v part))) +;; Make :notmuch-part front sticky and rear non-sticky so it stays +;; applied to the beginning of each line when we indent the message. +(notmuch-map-text-property beg (point) 'front-sticky + (lambda (v) (pushnew :notmuch-part v))) +(notmuch-map-text-property beg (point) 'rear-nonsticky + (lambda (v) (pushnew :notmuch-part v) (defun notmuch-show-insert-body (msg body depth) "Insert the body BODY at depth DEPTH in the current thread." @@ -1194,11 +1200,6 @@ reset based on the original query." "Submap for part commands") (fset 'notmuch-show-part-map notmuch-show-part-map) -(defvar notmuch-show-part-button-map - (make-composed-keymap notmuch-show-part-map button-map) - "Keymap for part button commands") -(fset 'notmuch-show-part-button-map notmuch-show-part-button-map) - (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) (define-key map "?" 'notmuch-help) @@ -1365,7 +1366,7 @@ Some useful entries are: (get-text-property (point) :notmuch-message-properties))) (defun notmuch-show-get-part-properties () - "Return the properties of the part containing point. + "Return the properties of the innermost part containing point. This is
[PATCH 0/4] emacs: Part command improvements
Quoth Mark Walters on May 27 at 11:30 pm: > Austin Clements writes: > > > This is a follow-up of sorts to id:"8761ycc19t.fsf at qmul.ac.uk", where > > Mark suggested that the part handling commands could all use the > > correponding mm-* functions. I ran with the idea and wound up with > > this series, which, in addition to standardizing on the mm-* functions > > for everything and simplifying the implementation overall, decouples > > the part commands from part buttons, which removes an entire layer > > from the implementation and adds the ability to invoke part commands > > with point anywhere in a part (something I often find myself wanting). > > Overall I really like this series. In addition to the clean up etc it > makes it easy to export the text/plain part (which doesn't have a part > button). I have recollection of this being difficult if it is base64 > encoded. Right. That's one of the reasons I wanted a global part keymap (and this series happened to be a convenient place to introduce that). Also helpful is that the part bindings now appear in the show help, which is good because I can never remember which key used the default viewer and which prompted for a viewer. > I have a few small comments > > As mentioned on irc (just included here in case other people are > testing) make-composed-keymap is emacs 24 only. I've removed the button map entirely, so this is no longer a problem. > This does change the default directory for saving: not serious but it's > probably worth deciding do we want to use mailcap-download-directory or > home or where emacs was started or? I don't really care what the default directory is, as long as we're consistent, which we currently aren't. mm-default-directory seems like a fine thing to be consistent with, since we use mm for everything else. > I don't know if we want to keep a special keymap for the button or just > always use the . prefix; the advantage is that you don't have 's' on a > button acting differently from 's' in the text (which has annoyed me > several times) otoh it is the extra keystroke which may annoy people > too. Let the bikeshedding begin! (obviously return for the default > action would remain. I'm all for removing the special button keymap. The less hidden functionality the better. > Would it be worth having . return in the part body as the default > action ? I played with this for a while and eventually decided it wasn't worth the effort. Maybe in a followup. > Finally, with message indenting it's the start/end of the part are a > little unclear. I think it's the [ of the part button at the start of > the part to the character before the [ of the next part button. In > particular on the line of a new part but before the button is still the > old part. Since parts are whole lines it would be nice if the region > were line based but I don't know if that is easy. Fixed in v2. > Best wishes > > Mark
v3 of --stderr=FILE patches
Tomi Ollila writes: > This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi > pushed, with one spelling correction in a commit message. d
v3 of --stderr=FILE patches
Just confirming LGTM +1 for this version too. Best wishes Mark Tomi Ollila writes: > This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi > > In id:m2a9nfr4tb.fsf at guru.guru-group.fi I suggested to use 0600 as > permission bits so that files written to /tmp would not have write > bits set in any case. That would have been inconsistent what is > normally expected in redirection cases. The problem I described > is easily avoided in emacs as (make-temp-file "nmerr") will create > file "/tmp/nmerrXX" with permissions 0600 -- and writing to > that already-created file will not change its permissions. Writing > elsewhere is usually covered with directory permissions. > > > Diffdiff from v2 is shown below. > > diff --git a/NEWS b/NEWS > index 990b038..80abd97 100644 > --- a/NEWS > +++ b/NEWS > @@ -38,8 +38,7 @@ Top level option to specify configuration file > Top level option to redirect writes to stderr > >With `notmuch --stderr=FILE` all writes to stderr are redirected to > - the specified file. If the file name is a plain '-', stderr is > - written to stdout. > + the specified file. If FILE is '-', stderr is redirected to stdout. > > Deprecated commands "part" and "search-tags" are removed. > > diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1 > index fbd575a..f5ca0ad 100644 > --- a/man/man1/notmuch.1 > +++ b/man/man1/notmuch.1 > @@ -83,7 +83,7 @@ configuration file specified by ${NOTMUCH_CONFIG}. > .B \-\-stderr=FILE > > Redirect all writes to stderr to the specified file. > -If the file name is a plain '-', stderr is written to stdout. > +If FILE is '-', stderr is redirected to stdout. > .RE > > .SH COMMANDS > diff --git a/notmuch.c b/notmuch.c > index 654a568..15e90c8 100644 > --- a/notmuch.c > +++ b/notmuch.c > @@ -260,7 +260,7 @@ redirect_stderr (const char * stderr_file) > return 1; > } > } else { > - int fd = open (stderr_file, O_WRONLY|O_CREAT|O_APPEND, 0644); > + int fd = open (stderr_file, O_WRONLY|O_CREAT|O_TRUNC, 0666); > if (fd < 0) { > fprintf (stderr, "Error: Cannot redirect stderr to '%s': %s\n", >stderr_file, strerror (errno)); > > > From Tomi Ollila # This line is ignored. > > ___ > notmuch mailing list > notmuch at notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch
v3 of --stderr=FILE patches
LGTM. Quoth Tomi Ollila on May 28 at 9:38 pm: > This is v3 of id:1369557954-13439-1-git-send-email-tomi.ollila at iki.fi > > In id:m2a9nfr4tb.fsf at guru.guru-group.fi I suggested to use 0600 as > permission bits so that files written to /tmp would not have write > bits set in any case. That would have been inconsistent what is > normally expected in redirection cases. The problem I described > is easily avoided in emacs as (make-temp-file "nmerr") will create > file "/tmp/nmerrXX" with permissions 0600 -- and writing to > that already-created file will not change its permissions. Writing > elsewhere is usually covered with directory permissions.
[PATCH v5 03/12] cli: add insert command
On Sun, 28 Apr 2013 00:24:28 +0300, Jani Nikula wrote: > On Wed, 03 Apr 2013, Peter Wang wrote: > > The notmuch insert command reads a message from standard input, > > writes it to a Maildir folder, and then incorporates the message into > > the notmuch database. Essentially it moves the functionality of > > notmuch-deliver into notmuch. > > > > Though it could be used as an alternative to notmuch new, the reason > > I want this is to allow my notmuch frontend to add postponed or sent > > messages to the mail store and notmuch database, without resorting to > > another tool (e.g. notmuch-deliver) nor directly modifying the maildir. > > --- > > Makefile.local | 1 + > > notmuch-client.h | 3 + > > notmuch-insert.c | 336 > > +++ > > notmuch.c| 3 + > > 4 files changed, 343 insertions(+) > > create mode 100644 notmuch-insert.c > > ... > > +/* Add the specified message file to the notmuch database, applying tags. > > + * The file is renamed to encode notmuch tags as maildir flags. */ > > +static notmuch_bool_t > > +add_file_to_database (notmuch_database_t *notmuch, const char *path, > > + tag_op_list_t *tag_ops) > > +{ > > +notmuch_message_t *message; > > +notmuch_status_t status; > > + > > +status = notmuch_database_add_message (notmuch, path, ); > > +switch (status) { > > +case NOTMUCH_STATUS_SUCCESS: > > +case NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID: > > + break; > > +default: > > +case NOTMUCH_STATUS_FILE_NOT_EMAIL: > > If such a message really arrives, the mail system will keep trying if > failure is returned. Maybe deliver the file without indexing, and return > success? > Rethinking it, if notmuch insert is going to used as a general mail delivery tool (not my own use case) then its primary job should be to get the file to disk. As long as that is done, we should return success. Indexing the message would be considered a bonus, and failure there or in syncing tags to flags should not cause the file to be deleted and an error code returned. (A warning can be written to standard error.) > > +case NOTMUCH_STATUS_READ_ONLY_DATABASE: > > +case NOTMUCH_STATUS_XAPIAN_EXCEPTION: > > +case NOTMUCH_STATUS_OUT_OF_MEMORY: > > +case NOTMUCH_STATUS_FILE_ERROR: > > +case NOTMUCH_STATUS_NULL_POINTER: > > +case NOTMUCH_STATUS_TAG_TOO_LONG: > > +case NOTMUCH_STATUS_UNBALANCED_FREEZE_THAW: > > +case NOTMUCH_STATUS_UNBALANCED_ATOMIC: > > +case NOTMUCH_STATUS_LAST_STATUS: > > + fprintf (stderr, "Error: failed to add `%s' to notmuch database: %s\n", > > +path, notmuch_status_to_string (status)); > > + return FALSE; > > +} > > + > > +if (status == NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID) { > > + /* Don't change tags of an existing message. */ > > + status = notmuch_message_tags_to_maildir_flags (message); > > + if (status != NOTMUCH_STATUS_SUCCESS) > > + fprintf (stderr, "Error: failed to sync tags to maildir flags\n"); > > +} else { > > + status = tag_op_list_apply (message, tag_ops, TAG_FLAG_MAILDIR_SYNC); > > Syncing tags to maildir flags is more interesting here than above. And > it should be done because notmuch insert allows arbitrary tags on the > command line. Having, for example, -unread or +flagged on the command > line makes the flags go out of sync. (notmuch new should do the syncing > too, but it's less important because it only adds new.tags.) > > However, calling notmuch_message_tags_to_maildir_flags() may rename the > file from new to cur, which blows up the directory syncing and file > unlinking on the error path in insert_message() below. We would sidestep these problems. > > +static notmuch_bool_t > > +insert_message (void *ctx, notmuch_database_t *notmuch, int fdin, > > + const char *dir, tag_op_list_t *tag_ops) > > +{ > > +char *tmppath; > > +char *newpath; > > +char *newdir; > > +int fdout; > > +char *cleanup_path; > > + > > +fdout = maildir_open_tmp_file (ctx, dir, , , ); > > +if (fdout < 0) > > + return FALSE; > > + > > +cleanup_path = tmppath; > > + > > +if (! copy_stdin (fdin, fdout)) > > + goto FAIL; > > + > > +if (fsync (fdout) != 0) { > > + fprintf (stderr, "Error: fsync failed: %s\n", strerror (errno)); > > + goto FAIL; > > +} > > + > > +close (fdout); > > +fdout = -1; > > + > > +/* Atomically move the new message file from the Maildir 'tmp' > > directory > > + * to the 'new' directory. We follow the Dovecot recommendation to > > + * simply use rename() instead of link() and unlink(). > > + * See also: > > http://wiki.dovecot.org/MailboxFormat/Maildir#Mail_delivery > > + */ > > +if (rename (tmppath, newpath) != 0) { > > + fprintf (stderr, "Error: rename() failed: %s\n", strerror (errno)); > > + goto FAIL; > > +} > > + > > +cleanup_path = newpath; > > + > > +if (!
Re: v3 of --stderr=FILE patches
Just confirming LGTM +1 for this version too. Best wishes Mark Tomi Ollila tomi.oll...@iki.fi writes: This is v3 of id:1369557954-13439-1-git-send-email-tomi.oll...@iki.fi In id:m2a9nfr4tb@guru.guru-group.fi I suggested to use 0600 as permission bits so that files written to /tmp would not have write bits set in any case. That would have been inconsistent what is normally expected in redirection cases. The problem I described is easily avoided in emacs as (make-temp-file nmerr) will create file /tmp/nmerrXX with permissions 0600 -- and writing to that already-created file will not change its permissions. Writing elsewhere is usually covered with directory permissions. Diffdiff from v2 is shown below. diff --git a/NEWS b/NEWS index 990b038..80abd97 100644 --- a/NEWS +++ b/NEWS @@ -38,8 +38,7 @@ Top level option to specify configuration file Top level option to redirect writes to stderr With `notmuch --stderr=FILE` all writes to stderr are redirected to - the specified file. If the file name is a plain '-', stderr is - written to stdout. + the specified file. If FILE is '-', stderr is redirected to stdout. Deprecated commands part and search-tags are removed. diff --git a/man/man1/notmuch.1 b/man/man1/notmuch.1 index fbd575a..f5ca0ad 100644 --- a/man/man1/notmuch.1 +++ b/man/man1/notmuch.1 @@ -83,7 +83,7 @@ configuration file specified by ${NOTMUCH_CONFIG}. .B \-\-stderr=FILE Redirect all writes to stderr to the specified file. -If the file name is a plain '-', stderr is written to stdout. +If FILE is '-', stderr is redirected to stdout. .RE .SH COMMANDS diff --git a/notmuch.c b/notmuch.c index 654a568..15e90c8 100644 --- a/notmuch.c +++ b/notmuch.c @@ -260,7 +260,7 @@ redirect_stderr (const char * stderr_file) return 1; } } else { - int fd = open (stderr_file, O_WRONLY|O_CREAT|O_APPEND, 0644); + int fd = open (stderr_file, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd 0) { fprintf (stderr, Error: Cannot redirect stderr to '%s': %s\n, stderr_file, strerror (errno)); From Tomi Ollila tomi.oll...@iki.fi # This line is ignored. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: v3 of --stderr=FILE patches
LGTM. Quoth Tomi Ollila on May 28 at 9:38 pm: This is v3 of id:1369557954-13439-1-git-send-email-tomi.oll...@iki.fi In id:m2a9nfr4tb@guru.guru-group.fi I suggested to use 0600 as permission bits so that files written to /tmp would not have write bits set in any case. That would have been inconsistent what is normally expected in redirection cases. The problem I described is easily avoided in emacs as (make-temp-file nmerr) will create file /tmp/nmerrXX with permissions 0600 -- and writing to that already-created file will not change its permissions. Writing elsewhere is usually covered with directory permissions. ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
Re: [PATCH 0/4] emacs: Part command improvements
Quoth Mark Walters on May 27 at 11:30 pm: Austin Clements amdra...@mit.edu writes: This is a follow-up of sorts to id:8761ycc19t@qmul.ac.uk, where Mark suggested that the part handling commands could all use the correponding mm-* functions. I ran with the idea and wound up with this series, which, in addition to standardizing on the mm-* functions for everything and simplifying the implementation overall, decouples the part commands from part buttons, which removes an entire layer from the implementation and adds the ability to invoke part commands with point anywhere in a part (something I often find myself wanting). Overall I really like this series. In addition to the clean up etc it makes it easy to export the text/plain part (which doesn't have a part button). I have recollection of this being difficult if it is base64 encoded. Right. That's one of the reasons I wanted a global part keymap (and this series happened to be a convenient place to introduce that). Also helpful is that the part bindings now appear in the show help, which is good because I can never remember which key used the default viewer and which prompted for a viewer. I have a few small comments As mentioned on irc (just included here in case other people are testing) make-composed-keymap is emacs 24 only. I've removed the button map entirely, so this is no longer a problem. This does change the default directory for saving: not serious but it's probably worth deciding do we want to use mailcap-download-directory or home or where emacs was started or? I don't really care what the default directory is, as long as we're consistent, which we currently aren't. mm-default-directory seems like a fine thing to be consistent with, since we use mm for everything else. I don't know if we want to keep a special keymap for the button or just always use the . prefix; the advantage is that you don't have 's' on a button acting differently from 's' in the text (which has annoyed me several times) otoh it is the extra keystroke which may annoy people too. Let the bikeshedding begin! (obviously return for the default action would remain. I'm all for removing the special button keymap. The less hidden functionality the better. Would it be worth having . return in the part body as the default action ? I played with this for a while and eventually decided it wasn't worth the effort. Maybe in a followup. Finally, with message indenting it's the start/end of the part are a little unclear. I think it's the [ of the part button at the start of the part to the character before the [ of the next part button. In particular on the line of a new part but before the button is still the old part. Since parts are whole lines it would be nice if the region were line based but I don't know if that is easy. Fixed in v2. Best wishes Mark ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 5/5] News for Emacs part handling changes
--- NEWS | 16 1 file changed, 16 insertions(+) diff --git a/NEWS b/NEWS index a7f2ec6..23f4c6a 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision. Emacs Interface --- +New keymap to view/save parts + + To view or save a single MIME part of a message, use the new . + submap (e.g., . s to save, . v to view). Previously, these keys + were only available when point was on a part button and they did not + have the . prefix, so they were difficult to invoke (impossible if + a part did not have a button) and clashed with other bindings. + These new bindings also appear in show's help, so you don't have to + memorize them. + +Default part save directory is now `mm-default-directory` + + Previously, notmuch offered to save parts and attachments to a mix + of `mm-default-directory`, `mailcap-download-directory`, and `~/`. + This has been standardized on `mm-default-directory`. + No Emacs 22 support The Emacs 22 support added late 2010 was sufficient only for a short -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 0/5] emacs: Part command improvements
This is v2 of id:87zjvghx82@qmul.ac.uk. In addition to some general improvements, this fixes the handling of part overlays in indented messages, removes the special part button map entirely in favor of the . submap, and adds a NEWS patch. The diff from v1 follows diff --git a/NEWS b/NEWS index a7f2ec6..23f4c6a 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,22 @@ notmuch-vim, but of course that is their decision. Emacs Interface --- +New keymap to view/save parts + + To view or save a single MIME part of a message, use the new . + submap (e.g., . s to save, . v to view). Previously, these keys + were only available when point was on a part button and they did not + have the . prefix, so they were difficult to invoke (impossible if + a part did not have a button) and clashed with other bindings. + These new bindings also appear in show's help, so you don't have to + memorize them. + +Default part save directory is now `mm-default-directory` + + Previously, notmuch offered to save parts and attachments to a mix + of `mm-default-directory`, `mailcap-download-directory`, and `~/`. + This has been standardized on `mm-default-directory`. + No Emacs 22 support The Emacs 22 support added late 2010 was sufficient only for a short diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 09ce25e..2186783 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -360,21 +360,17 @@ OBJECT. below string)) -(defun notmuch-put-text-property-if-nil (start end property value - optional object) - Like `put-text-property', but only set the property where it is nil. +(defun notmuch-map-text-property (start end prop func optional object) + Transform text property PROP using FUNC. + +Applies FUNC to each distinct value of the text property PROP +between START and END of OBJECT, setting PROP to the value +returned by FUNC. (while ( start end) -(let ((start-nil (text-property-any start end property nil object))) - (if (null start-nil) - ;; There are no more nil regions; exit the loop - (setq start end) - ;; Find the end of the nil region - (let ((end-nil - (or (text-property-not-all start-nil end property nil object) - end))) - ;; Set the property - (put-text-property start-nil end-nil property value object) - (setq start end-nil)) +(let ((value (get-text-property start prop object)) + (next (next-single-property-change start prop object end))) + (put-text-property start next prop (funcall func value) object) + (setq start next (defun notmuch-logged-error (msg optional extra) Log MSG and EXTRA to *Notmuch errors* and signal MSG. diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 380b144..613e666 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -466,7 +466,6 @@ message at DEPTH in the current thread. (define-button-type 'notmuch-show-part-button-type 'action 'notmuch-show-part-button-default - 'keymap 'notmuch-show-part-button-map 'follow-link t 'face 'message-mml :supertype 'notmuch-button-type) @@ -843,8 +842,15 @@ If HIDE is non-nil then initially hide this part. (insert \n)) (notmuch-show-create-part-overlays msg beg (point) hide) ;; Record part information. Since we already inserted subparts, -;; don't override exiting :notmuch-part properties. -(notmuch-put-text-property-if-nil beg (point) :notmuch-part part))) +;; don't override existing :notmuch-part properties. +(notmuch-map-text-property beg (point) :notmuch-part + (lambda (v) (or v part))) +;; Make :notmuch-part front sticky and rear non-sticky so it stays +;; applied to the beginning of each line when we indent the message. +(notmuch-map-text-property beg (point) 'front-sticky + (lambda (v) (pushnew :notmuch-part v))) +(notmuch-map-text-property beg (point) 'rear-nonsticky + (lambda (v) (pushnew :notmuch-part v) (defun notmuch-show-insert-body (msg body depth) Insert the body BODY at depth DEPTH in the current thread. @@ -1194,11 +1200,6 @@ reset based on the original query. Submap for part commands) (fset 'notmuch-show-part-map notmuch-show-part-map) -(defvar notmuch-show-part-button-map - (make-composed-keymap notmuch-show-part-map button-map) - Keymap for part button commands) -(fset 'notmuch-show-part-button-map notmuch-show-part-button-map) - (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) (define-key map ? 'notmuch-help) @@ -1365,7 +1366,7 @@ Some useful entries are: (get-text-property (point) :notmuch-message-properties))) (defun notmuch-show-get-part-properties () - Return the properties of the part containing point. + Return the properties of the innermost part containing point. This is
[PATCH v2 1/5] emacs: Retain text properties when toggling buttons
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. --- emacs/notmuch-show.el |2 ++ emacs/notmuch-wash.el |2 ++ 2 files changed, 4 insertions(+) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index b0a8d8a..a080134 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -559,10 +559,12 @@ message at DEPTH in the current thread. (new-start (button-start button)) (button-label (button-get button :base-label)) (old-point (point)) +(properties (text-properties-at (point))) (inhibit-read-only t)) (overlay-put overlay 'invisible (not show)) (goto-char new-start) (insert [ button-label (if show ] (hidden) ])) + (set-text-properties new-start (point) properties) (let ((old-end (button-end button))) (move-overlay button new-start (point)) (delete-region (point) old-end)) diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 8a68819..8fe91e1 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -104,9 +104,11 @@ lower).) (overlay (button-get cite-button 'overlay)) (button-label (notmuch-wash-button-label overlay)) (old-point (point)) +(properties (text-properties-at (point))) (inhibit-read-only t)) (goto-char new-start) (insert button-label) +(set-text-properties new-start (point) properties) (let ((old-end (button-end cite-button))) (move-overlay cite-button new-start (point)) (delete-region (point) old-end)) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 2/5] emacs: Record part p-list in a text property
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. --- emacs/notmuch-lib.el | 12 emacs/notmuch-show.el | 20 +++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 790136e..2186783 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -360,6 +360,18 @@ OBJECT. below string)) +(defun notmuch-map-text-property (start end prop func optional object) + Transform text property PROP using FUNC. + +Applies FUNC to each distinct value of the text property PROP +between START and END of OBJECT, setting PROP to the value +returned by FUNC. + (while ( start end) +(let ((value (get-text-property start prop object)) + (next (next-single-property-change start prop object end))) + (put-text-property start next prop (funcall func value) object) + (setq start next + (defun notmuch-logged-error (msg optional extra) Log MSG and EXTRA to *Notmuch errors* and signal MSG. diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index a080134..e84e1ba 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -900,7 +900,17 @@ If HIDE is non-nil then initially hide this part. ;; Ensure that the part ends with a carriage return. (unless (bolp) (insert \n)) -(notmuch-show-create-part-overlays msg beg (point) hide))) +(notmuch-show-create-part-overlays msg beg (point) hide) +;; Record part information. Since we already inserted subparts, +;; don't override existing :notmuch-part properties. +(notmuch-map-text-property beg (point) :notmuch-part + (lambda (v) (or v part))) +;; Make :notmuch-part front sticky and rear non-sticky so it stays +;; applied to the beginning of each line when we indent the message. +(notmuch-map-text-property beg (point) 'front-sticky + (lambda (v) (pushnew :notmuch-part v))) +(notmuch-map-text-property beg (point) 'rear-nonsticky + (lambda (v) (pushnew :notmuch-part v) (defun notmuch-show-insert-body (msg body depth) Insert the body BODY at depth DEPTH in the current thread. @@ -1404,6 +1414,14 @@ Some useful entries are: (notmuch-show-move-to-message-top) (get-text-property (point) :notmuch-message-properties))) +(defun notmuch-show-get-part-properties () + Return the properties of the innermost part containing point. + +This is the part property list retrieved from the CLI. Signals +an error if there is no part containing point. + (or (get-text-property (point) :notmuch-part) + (error No message part here))) + (defun notmuch-show-set-prop (prop val optional props) (let ((inhibit-read-only t) (props (or props -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch
[PATCH v2 4/5] emacs: Bind MIME part commands to . submap
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. --- emacs/notmuch-show.el | 23 +++ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el index 0d9a34c..613e666 100644 --- a/emacs/notmuch-show.el +++ b/emacs/notmuch-show.el @@ -466,22 +466,10 @@ message at DEPTH in the current thread. (define-button-type 'notmuch-show-part-button-type 'action 'notmuch-show-part-button-default - 'keymap 'notmuch-show-part-button-map 'follow-link t 'face 'message-mml :supertype 'notmuch-button-type) -(defvar notmuch-show-part-button-map - (let ((map (make-sparse-keymap))) -(set-keymap-parent map button-map) -(define-key map s 'notmuch-show-save-part) -(define-key map v 'notmuch-show-view-part) -(define-key map o 'notmuch-show-interactively-view-part) -(define-key map | 'notmuch-show-pipe-part) -map) - Submap for button commands) -(fset 'notmuch-show-part-button-map notmuch-show-part-button-map) - (defun notmuch-show-insert-part-header (nth content-type declared-type optional name comment) (let ((button) (base-label (concat (when name (concat name : )) @@ -1202,6 +1190,16 @@ reset based on the original query. Submap for stash commands) (fset 'notmuch-show-stash-map notmuch-show-stash-map) +(defvar notmuch-show-part-map + (let ((map (make-sparse-keymap))) +(define-key map s 'notmuch-show-save-part) +(define-key map v 'notmuch-show-view-part) +(define-key map o 'notmuch-show-interactively-view-part) +(define-key map | 'notmuch-show-pipe-part) +map) + Submap for part commands) +(fset 'notmuch-show-part-map notmuch-show-part-map) + (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) (define-key map ? 'notmuch-help) @@ -1244,6 +1242,7 @@ reset based on the original query. (define-key map $ 'notmuch-show-toggle-process-crypto) (define-key map 'notmuch-show-toggle-thread-indentation) (define-key map t 'toggle-truncate-lines) + (define-key map . 'notmuch-show-part-map) map) Keymap for \notmuch show\ buffers.) (fset 'notmuch-show-mode-map notmuch-show-mode-map) -- 1.7.10.4 ___ notmuch mailing list notmuch@notmuchmail.org http://notmuchmail.org/mailman/listinfo/notmuch