aboutsummaryrefslogtreecommitdiffhomepage
path: root/emacs/notmuch-wash.el
blob: 5ca567f59be6ad1cc43a4864253e1e9f44979012 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
;; notmuch-wash.el --- cleaning up message bodies
;;
;; Copyright © Carl Worth
;;
;; This file is part of Notmuch.
;;
;; Notmuch is free software: you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; Notmuch is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with Notmuch.  If not, see <http://www.gnu.org/licenses/>.
;;
;; Authors: Carl Worth <cworth@cworth.org>

(defvar notmuch-wash-signature-regexp
  "^\\(-- ?\\|_+\\)$"
  "Pattern to match a line that separates content from signature.")

(defvar notmuch-wash-citation-regexp
  "\\(^[[:space:]]*>.*\n\\)+"
  "Pattern to match citation lines.")

(defvar notmuch-wash-signature-button-format
  "[ %d-line signature. Click/Enter to toggle visibility. ]"
  "String used to construct button text for hidden signatures.
Can use up to one integer format parameter, i.e. %d")

(defvar notmuch-wash-citation-button-format
  "[ %d more citation lines. Click/Enter to toggle visibility. ]"
  "String used to construct button text for hidden citations.
Can use up to one integer format parameter, i.e. %d")

(defvar notmuch-wash-signature-lines-max 12
  "Maximum length of signature that will be hidden by default.")

(defvar 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.")

(defvar 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.")

(defun notmuch-wash-toggle-invisible-action (cite-button)
  (let ((invis-spec (button-get cite-button 'invisibility-spec)))
    (if (invisible-p invis-spec)
	(remove-from-invisibility-spec invis-spec)
      (add-to-invisibility-spec invis-spec)))
  (force-window-update)
  (redisplay t))

(define-button-type 'notmuch-wash-button-invisibility-toggle-type
  'action 'notmuch-wash-toggle-invisible-action
  'follow-link t
  'face 'font-lock-comment-face)

(define-button-type 'notmuch-wash-button-citation-toggle-type
  'help-echo "mouse-1, RET: Show citation"
  :supertype 'notmuch-wash-button-invisibility-toggle-type)

(define-button-type 'notmuch-wash-button-signature-toggle-type
  'help-echo "mouse-1, RET: Show signature"
  :supertype 'notmuch-wash-button-invisibility-toggle-type)

(defun notmuch-wash-region-isearch-show (overlay)
  (remove-from-invisibility-spec (overlay-get overlay 'invisible)))

(defun notmuch-wash-region-to-button (beg end type prefix button-text)
  "Auxilary 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.  BUTTON-TEXT
is what to put on the button."

  ;; 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))
	(invis-spec (make-symbol (concat "notmuch-" type "-region")))
	(button-type (intern-soft (concat "notmuch-wash-button-"
					  type "-toggle-type"))))
    (add-to-invisibility-spec invis-spec)
    (overlay-put overlay 'invisible invis-spec)
    (overlay-put overlay 'isearch-open-invisible #'notmuch-wash-region-isearch-show)
    (goto-char (1+ end))
    (save-excursion
      (goto-char (1- beg))
      (insert prefix)
      (insert-button button-text
		     'invisibility-spec invis-spec
		     :type button-type))))

(defun notmuch-wash-text/plain-citations (depth)
  "Markup citations, and up to one signature in the buffer."
  (goto-char (point-min))
  (beginning-of-line)
  (while (and (< (point) (point-max))
	      (re-search-forward notmuch-wash-citation-regexp nil t))
    (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-face)
      (when (> cite-lines (+ notmuch-wash-citation-lines-prefix
			     notmuch-wash-citation-lines-suffix
			     1))
	(goto-char cite-start)
	(forward-line notmuch-wash-citation-lines-prefix)
	(let ((hidden-start (point-marker)))
	  (goto-char cite-end)
	  (forward-line (- notmuch-wash-citation-lines-suffix))
	  (notmuch-wash-region-to-button
	   hidden-start (point-marker)
	   "citation" "\n"
	   (format notmuch-wash-citation-button-format
		   (- cite-lines
		      notmuch-wash-citation-lines-prefix
		      notmuch-wash-citation-lines-suffix)))))))
  (if (and (not (eobp))
	   (re-search-forward notmuch-wash-signature-regexp nil t))
      (let* ((sig-start (match-beginning 0))
	     (sig-end (match-end 0))
	     (sig-lines (1- (count-lines sig-start (point-max)))))
	(if (<= sig-lines notmuch-wash-signature-lines-max)
	    (let ((sig-start-marker (make-marker))
		  (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-face)
	      (notmuch-wash-region-to-button
	       sig-start-marker sig-end-marker
	       "signature" "\n"
	       (format notmuch-wash-signature-button-format sig-lines)))))))

;;

(provide 'notmuch-wash)