-;; notmuch-wash.el --- cleaning up message bodies
+;;; notmuch-wash.el --- cleaning up message bodies
;;
;; Copyright © Carl Worth
;; Copyright © David Edmondson
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
-;; along with Notmuch. If not, see <http://www.gnu.org/licenses/>.
+;; along with Notmuch. If not, see <https://www.gnu.org/licenses/>.
;;
;; Authors: Carl Worth <cworth@cworth.org>
;; David Edmondson <dme@dme.org>
+;;; Code:
+
(require 'coolj)
+(require 'notmuch-lib)
-(declare-function notmuch-show-insert-bodypart "notmuch-show" (msg part depth))
+(declare-function notmuch-show-insert-bodypart "notmuch-show"
+ (msg part depth &optional hide))
+(defvar notmuch-show-indent-messages-width)
;;
-(defvar notmuch-wash-signature-regexp
- "^\\(-- ?\\|_+\\)$"
- "Pattern to match a line that separates content from signature.")
+(defgroup notmuch-wash nil
+ "Cleaning up messages for display."
+ :group 'notmuch)
+
+(defcustom notmuch-wash-signature-regexp "^\\(-- ?\\|_+\\)$"
+ "Pattern to match a line that separates content from signature."
+ :type 'regexp
+ :group 'notmuch-wash)
-(defvar notmuch-wash-citation-regexp
- "\\(^[[:space:]]*>.*\n\\)+"
- "Pattern to match citation lines.")
+(defcustom notmuch-wash-citation-regexp "\\(^[[:space:]]*>.*\n\\)+"
+ "Pattern to match citation lines."
+ :type 'regexp
+ :group 'notmuch-wash)
-(defvar notmuch-wash-original-regexp "^\\(--+\s?[oO]riginal [mM]essage\s?--+\\)$"
- "Pattern to match a line that separates original message from reply in top-posted message.")
+(defcustom notmuch-wash-original-regexp "^\\(--+\s?[oO]riginal [mM]essage\s?--+\\)$"
+ "Pattern to match a line that separates original message from
+reply in top-posted message."
+ :type 'regexp
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-signature-hidden-format
+(defcustom notmuch-wash-button-signature-hidden-format
"[ %d-line signature. Click/Enter to show. ]"
"String used to construct button text for hidden signatures.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-signature-visible-format
+(defcustom notmuch-wash-button-signature-visible-format
"[ %d-line signature. Click/Enter to hide. ]"
"String used to construct button text for visible signatures.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-citation-hidden-format
+(defcustom notmuch-wash-button-citation-hidden-format
"[ %d more citation lines. Click/Enter to show. ]"
"String used to construct button text for hidden citations.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-citation-visible-format
+(defcustom notmuch-wash-button-citation-visible-format
"[ %d more citation lines. Click/Enter to hide. ]"
"String used to construct button text for visible citations.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-original-hidden-format
+(defcustom notmuch-wash-button-original-hidden-format
"[ %d-line hidden original message. Click/Enter to show. ]"
"String used to construct button text for hidden citations.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-button-original-visible-format
+(defcustom notmuch-wash-button-original-visible-format
"[ %d-line original message. Click/Enter to hide. ]"
"String used to construct button text for visible citations.
-Can use up to one integer format parameter, i.e. %d")
+Can use up to one integer format parameter, i.e. %d."
+ :type 'string
+ :group 'notmuch-wash)
-(defvar notmuch-wash-signature-lines-max 12
- "Maximum length of signature that will be hidden by default.")
+(defcustom notmuch-wash-signature-lines-max 12
+ "Maximum length of signature that will be hidden by default."
+ :type 'integer
+ :group 'notmuch-wash)
-(defvar notmuch-wash-citation-lines-prefix 3
+(defcustom notmuch-wash-citation-lines-prefix 3
"Always show at least this many lines from the start of a citation.
If there is one more line than the sum of
`notmuch-wash-citation-lines-prefix' and
`notmuch-wash-citation-lines-suffix', show that, otherwise
-collapse the remaining lines into a button.")
+collapse the remaining lines into a button."
+ :type 'integer
+ :group 'notmuch-wash)
-(defvar notmuch-wash-citation-lines-suffix 3
+(defcustom notmuch-wash-citation-lines-suffix 3
"Always show at least this many lines from the end of a citation.
If there is one more line than the sum of
`notmuch-wash-citation-lines-prefix' and
`notmuch-wash-citation-lines-suffix', show that, otherwise
-collapse the remaining lines into a button.")
+collapse the remaining lines into a button."
+ :type 'integer
+ :group 'notmuch-wash)
-(defvar notmuch-wash-wrap-lines-length nil
+(defcustom notmuch-wash-wrap-lines-length nil
"Wrap line after at most this many characters.
If this is nil, lines in messages will be wrapped to fit in the
current window. If this is a number, lines will be wrapped after
-this many characters or at the window width (whichever one is
-lower).")
+this many characters (ignoring indentation due to thread depth)
+or at the window width (whichever one is lower)."
+ :type '(choice (const :tag "window width" nil)
+ (integer :tag "number of characters"))
+ :group 'notmuch-wash)
+
+(defface notmuch-wash-toggle-button
+ '((t (:inherit font-lock-comment-face)))
+ "Face used for buttons toggling the visibility of washed away
+message parts."
+ :group 'notmuch-wash
+ :group 'notmuch-faces)
+
+(defface notmuch-wash-cited-text
+ '((t (:inherit message-cited-text)))
+ "Face used for cited text."
+ :group 'notmuch-wash
+ :group 'notmuch-faces)
(defun notmuch-wash-toggle-invisible-action (cite-button)
;; Toggle overlay visibility
(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))
(define-button-type 'notmuch-wash-button-invisibility-toggle-type
'action 'notmuch-wash-toggle-invisible-action
'follow-link t
- 'face 'font-lock-comment-face
+ 'face 'notmuch-wash-toggle-button
:supertype 'notmuch-button-type)
(define-button-type 'notmuch-wash-button-citation-toggle-type
(let* ((type (overlay-get overlay 'type))
(invis-spec (overlay-get overlay 'invisible))
(state (if (invisible-p invis-spec) "hidden" "visible"))
- (label-format (symbol-value (intern-soft (concat "notmuch-wash-button-"
- type "-" state "-format"))))
- (lines-count (count-lines (overlay-start overlay) (overlay-end overlay))))
+ (label-format (symbol-value
+ (intern-soft
+ (format "notmuch-wash-button-%s-%s-format"
+ type state))))
+ (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 &optional prefix)
- "Auxiliary function to do the actual making of overlays and buttons
+ "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\". 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
;; replacing intern-soft with make-symbol will cause this to fail,
;; since the newly created symbol has no plist.
-
(let ((overlay (make-overlay beg end))
(button-type (intern-soft (concat "notmuch-wash-button-"
type "-toggle-type"))))
(let* ((cite-start (match-beginning 0))
(cite-end (match-end 0))
(cite-lines (count-lines cite-start cite-end)))
- (overlay-put (make-overlay cite-start cite-end) 'face 'message-cited-text)
+ (overlay-put (make-overlay cite-start cite-end)
+ 'face 'notmuch-wash-cited-text)
(when (> cite-lines (+ notmuch-wash-citation-lines-prefix
notmuch-wash-citation-lines-suffix
1))
(sig-end-marker (make-marker)))
(set-marker sig-start-marker sig-start)
(set-marker sig-end-marker (point-max))
- (overlay-put (make-overlay sig-start-marker sig-end-marker) 'face 'message-cited-text)
+ (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"))))))
(defun notmuch-wash-elide-blank-lines (msg depth)
"Elide leading, trailing and successive blank lines."
-
;; Algorithm derived from `article-strip-multiple-blank-lines' in
;; `gnus-art.el'.
-
;; Make all blank lines empty.
(goto-char (point-min))
(while (re-search-forward "^[[:space:]\t]+$" nil t)
(replace-match "" nil t))
-
;; Replace multiple empty lines with a single empty line.
(goto-char (point-min))
(while (re-search-forward "^\n\\(\n+\\)" nil t)
(delete-region (match-beginning 1) (match-end 1)))
-
;; Remove a leading blank line.
(goto-char (point-min))
(if (looking-at "\n")
(delete-region (match-beginning 0) (match-end 0)))
-
;; Remove a trailing blank line.
(goto-char (point-max))
(if (looking-at "\n")
text,
- Remove citation trailers standing alone after a block of cited
text."
-
;; Remove lines of repeated citation leaders with no other content.
(goto-char (point-min))
(while (re-search-forward "\\(^>[> ]*\n\\)\\{2,\\}" nil t)
(replace-match "\\1"))
-
- ;; Remove citation leaders standing alone before a block of cited
- ;; text.
+ ;; Remove citation leaders standing alone before a block of cited text.
(goto-char (point-min))
(while (re-search-forward "\\(\n\\|^[^>].*\\)\n\\(^>[> ]*\n\\)" nil t)
(replace-match "\\1\n"))
-
- ;; Remove citation trailers standing alone after a block of cited
- ;; text.
+ ;; Remove citation trailers standing alone after a block of cited text.
(goto-char (point-min))
(while (re-search-forward "\\(^>[> ]*\n\\)\\(^$\\|^[^>].*\\)" nil t)
(replace-match "\\2")))
its value. Otherwise, this function will wrap long lines in the
message at the window width. When doing so, citation leaders in
the wrapped text are maintained."
-
(let* ((coolj-wrap-follows-window-size nil)
+ (indent (* depth notmuch-show-indent-messages-width))
(limit (if (numberp notmuch-wash-wrap-lines-length)
- (min notmuch-wash-wrap-lines-length
+ (min (+ notmuch-wash-wrap-lines-length indent)
(window-width))
(window-width)))
(fill-column (- limit
- depth
+ indent
;; 2 to avoid poor interaction with
;; `word-wrap'.
2)))
Given that this function guesses whether a buffer includes a
patch and then guesses the extent of the patch, there is scope
for error."
-
(goto-char (point-min))
(when (re-search-forward diff-file-header-re nil t)
(beginning-of-line -1)
(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-type "inline patch"))
(setq part (plist-put part :content (buffer-string)))
(setq part (plist-put part :id -1))
(setq part (plist-put part :filename
;;
(provide 'notmuch-wash)
+
+;;; notmuch-wash.el ends here