X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=emacs%2Fnotmuch-wash.el;h=56981d0635aad98913ae90e46f88f3e739fa261d;hp=1f420b25a05d770556cd19e4e737f522b7e18098;hb=90f310b4fb8903898ead674059584737e448eb8a;hpb=432e091924c1d1d8950a44ca78bc5b9c5ade47e4 diff --git a/emacs/notmuch-wash.el b/emacs/notmuch-wash.el index 1f420b25..56981d06 100644 --- a/emacs/notmuch-wash.el +++ b/emacs/notmuch-wash.el @@ -136,12 +136,13 @@ collapse the remaining lines into a button.") (lines-count (count-lines (overlay-start overlay) (overlay-end overlay)))) (format label-format lines-count))) -(defun notmuch-wash-region-to-button (msg beg end type prefix) +(defun notmuch-wash-region-to-button (msg beg end type &optional prefix) "Auxiliary function to do the actual making of overlays and buttons BEG and END are buffer locations. TYPE should a string, either -\"citation\" or \"signature\". PREFIX is some arbitrary text to -insert before the button, probably for indentation." +\"citation\" or \"signature\". Optional PREFIX is some arbitrary +text to insert before the button, probably for indentation. Note +that PREFIX should not include a newline." ;; This uses some slightly tricky conversions between strings and ;; symbols because of the way the button code works. Note that @@ -160,12 +161,15 @@ insert before the button, probably for indentation." (overlay-put overlay 'type type) (goto-char (1+ end)) (save-excursion - (goto-char (1- beg)) - (insert prefix) - (insert-button (notmuch-wash-button-label overlay) + (goto-char beg) + (if prefix + (insert-before-markers prefix)) + (let ((button-beg (point))) + (insert-before-markers (notmuch-wash-button-label overlay) "\n") + (make-button button-beg (1- (point)) 'invisibility-spec invis-spec 'overlay overlay - :type button-type)))) + :type button-type))))) (defun notmuch-wash-excerpt-citations (msg depth) "Excerpt citations and up to one signature." @@ -177,7 +181,7 @@ insert before the button, probably for indentation." (msg-end (point-max)) (msg-lines (count-lines msg-start msg-end))) (notmuch-wash-region-to-button - msg msg-start msg-end "original" "\n"))) + msg msg-start msg-end "original"))) (while (and (< (point) (point-max)) (re-search-forward notmuch-wash-citation-regexp nil t)) (let* ((cite-start (match-beginning 0)) @@ -194,7 +198,7 @@ insert before the button, probably for indentation." (forward-line (- notmuch-wash-citation-lines-suffix)) (notmuch-wash-region-to-button msg hidden-start (point-marker) - "citation" "\n"))))) + "citation"))))) (if (and (not (eobp)) (re-search-forward notmuch-wash-signature-regexp nil t)) (let* ((sig-start (match-beginning 0)) @@ -208,7 +212,7 @@ insert before the button, probably for indentation." (overlay-put (make-overlay sig-start-marker sig-end-marker) 'face 'message-cited-text) (notmuch-wash-region-to-button msg sig-start-marker sig-end-marker - "signature" "\n")))))) + "signature")))))) ;; @@ -290,6 +294,44 @@ When doing so, maintaining citation leaders in the wrapped text." (defvar diff-file-header-re) ; From `diff-mode.el'. +(defun notmuch-wash-subject-to-filename (subject &optional maxlen) + "Convert a mail SUBJECT into a filename. + +The resulting filename is similar to the names generated by \"git +format-patch\", without the leading patch sequence number +\"0001-\" and \".patch\" extension. Any leading \"[PREFIX]\" +style strings are removed prior to conversion. + +Optional argument MAXLEN is the maximum length of the resulting +filename, before trimming any trailing . and - characters." + (let* ((s (replace-regexp-in-string "^ *\\(\\[[^]]*\\] *\\)*" "" subject)) + (s (replace-regexp-in-string "[^A-Za-z0-9._]+" "-" s)) + (s (replace-regexp-in-string "\\.+" "." s)) + (s (if maxlen (substring s 0 (min (length s) maxlen)) s)) + (s (replace-regexp-in-string "[.-]*$" "" s))) + s)) + +(defun notmuch-wash-subject-to-patch-sequence-number (subject) + "Convert a patch mail SUBJECT into a patch sequence number. + +Return the patch sequence number N from the last \"[PATCH N/M]\" +style prefix in SUBJECT, or nil if such a prefix can't be found." + (when (string-match + "^ *\\(\\[[^]]*\\] *\\)*\\[[^]]*?\\([0-9]+\\)/[0-9]+[^]]*\\].*" + subject) + (string-to-number (substring subject (match-beginning 2) (match-end 2))))) + +(defun notmuch-wash-subject-to-patch-filename (subject) + "Convert a patch mail SUBJECT into a filename. + +The resulting filename is similar to the names generated by \"git +format-patch\". If the patch mail was generated and sent using +\"git format-patch/send-email\", this should re-create the +original filename the sender had." + (format "%04d-%s.patch" + (or (notmuch-wash-subject-to-patch-sequence-number subject) 1) + (notmuch-wash-subject-to-filename subject 52))) + (defun notmuch-wash-convert-inline-patch-to-part (msg depth) "Convert an inline patch into a fake 'text/x-diff' attachment. @@ -298,27 +340,29 @@ patch and then guesses the extent of the patch, there is scope for error." (goto-char (point-min)) - (if (re-search-forward diff-file-header-re nil t) - (progn - (beginning-of-line -1) - (let ((patch-start (point)) - (patch-end (point-max)) - part) - (goto-char patch-start) - (if (or - ;; Patch ends with signature. - (re-search-forward notmuch-wash-signature-regexp nil t) - ;; Patch ends with bugtraq comment. - (re-search-forward "^\\*\\*\\* " nil t)) - (setq patch-end (match-beginning 0))) - (save-restriction - (narrow-to-region patch-start patch-end) - (setq part (plist-put part :content-type "text/x-diff")) - (setq part (plist-put part :content (buffer-string))) - (setq part (plist-put part :id -1)) - (setq part (plist-put part :filename "inline patch")) - (delete-region (point-min) (point-max)) - (notmuch-show-insert-bodypart nil part depth)))))) + (when (re-search-forward diff-file-header-re nil t) + (beginning-of-line -1) + (let ((patch-start (point)) + (patch-end (point-max)) + part) + (goto-char patch-start) + (if (or + ;; Patch ends with signature. + (re-search-forward notmuch-wash-signature-regexp nil t) + ;; Patch ends with bugtraq comment. + (re-search-forward "^\\*\\*\\* " nil t)) + (setq patch-end (match-beginning 0))) + (save-restriction + (narrow-to-region patch-start patch-end) + (setq part (plist-put part :content-type "inline-patch-fake-part")) + (setq part (plist-put part :content (buffer-string))) + (setq part (plist-put part :id -1)) + (setq part (plist-put part :filename + (notmuch-wash-subject-to-patch-filename + (plist-get + (plist-get msg :headers) :Subject)))) + (delete-region (point-min) (point-max)) + (notmuch-show-insert-bodypart nil part depth))))) ;;