[notmuch] [PATCH v3] notmuch.el: Refactor citation markup. Variables for minimum size, button text.

david at tethera.net david at tethera.net
Sat Jan 16 05:44:53 PST 2010


From: David Bremner <bremner at unb.ca>

This is a fairly intrusive rewrite.

- I pulled the common code for the signature and citation case out
  into a separate function. This is not so much shorter, but I think it
  will be easier to maintain.

- I treated top posted copies essentially like signatures, except that I didn't
  sanity check their length, since neither do their senders.  I don't know if
  people would find it useful to see the first few lines in a top posted copy;
  I left it off in this version.

- I replaced the sequence of (looking-at blah) (forward-line)  with a single
  re-search-forward per citation.

New user-visible variables

- notmuch-show-signature-button-format, notmuch-show-citation-button-format,
  notmuch-show-original-button-format
  Allow customization of button text.

- notmuch-show-citation-lines-prefix
  Show this much of the citation before hiding
---

This is the third rewrite of this patch. For some reason I squashed
the series this time, but I still have the other branch if that would be helpful.
Essentially after using the patches for a while, I no longer thought that people would like 
one patch without the others.

 notmuch.el |  177 +++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 127 insertions(+), 50 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 97914f2..4b84b55 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -88,13 +88,44 @@
 The regexp can (and should) include $ to match the end of the
 line, but should not include ^ to match the beginning of the
 line. This is because notmuch may have inserted additional space
-for indentation at the beginning of the line. But notmuch will
-move past the indentation when testing this pattern, (so that the
-pattern can still test against the entire line).")
+for indentation at the beginning of the line.")
+
+(defvar notmuch-show-original-regexp "\\(--+\s?[oO]riginal [mM]essage\s?--+\\)$"
+  "Pattern to match a line that separates original message from reply in top-posted message.
+
+The regexp can (and should) include $ to match the end of the
+line, but should not include ^ to match the beginning of the
+line. This is because notmuch may have inserted additional space
+for indentation at the beginning of the line.")
+
+(defvar notmuch-show-signature-button-format 
+  "[ %d-line hidden 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")
+
+(defvar notmuch-show-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-show-original-button-format 
+  "[ %d-line hidden original message. Click/Enter to show ]"
+  "String used to construct button text for hidden copies of messages
+
+Can use up to one integer format parameter, i.e. %d")
+
 
 (defvar notmuch-show-signature-lines-max 12
   "Maximum length of signature that will be hidden by default.")
 
+(defvar notmuch-show-citation-lines-prefix 4
+  "Always show at least this many lines of a citation.
+
+If there is one more line, show that, otherwise collapse
+remaining lines into a button.")
+
 (defvar notmuch-command "notmuch"
   "Command to run the notmuch binary.")
 
@@ -586,6 +617,9 @@ which this thread was originally shown."
   :supertype 'notmuch-button-invisibility-toggle-type)
 (define-button-type 'notmuch-button-signature-toggle-type 'help-echo "mouse-1, RET: Show signature"
   :supertype 'notmuch-button-invisibility-toggle-type)
+(define-button-type 'notmuch-button-original-toggle-type 'help-echo "mouse-1, RET: Show original message"
+  :supertype 'notmuch-button-invisibility-toggle-type)
+
 (define-button-type 'notmuch-button-headers-toggle-type 'help-echo "mouse-1, RET: Show headers"
   :supertype 'notmuch-button-invisibility-toggle-type)
 (define-button-type 'notmuch-button-body-toggle-type
@@ -593,54 +627,97 @@ which this thread was originally shown."
   'face 'notmuch-message-summary-face
   :supertype 'notmuch-button-invisibility-toggle-type)
 
+(defun notmuch-show-citation-regexp (depth)
+  "Build a regexp for matching citations at a given DEPTH (indent)"
+  (let ((line-regexp (format "[[:space:]]\\{%d\\}>.*\n" depth)))
+    (concat "\\(?:^" line-regexp 
+	    "\\(?:[[:space:]]*\n" line-regexp
+	    "\\)?\\)+")))
+
+(defun notmuch-show-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-button-" 
+					  type "-toggle-type"))))
+    (add-to-invisibility-spec invis-spec)
+    (overlay-put overlay 'invisible invis-spec)
+    (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-show-markup-citations-region (beg end depth)
-  (goto-char beg)
-  (beginning-of-line)
-  (while (< (point) end)
-    (let ((beg-sub (point-marker))
-	  (indent (make-string depth ? ))
-	  (citation ">"))
-      (move-to-column depth)
-      (if (looking-at citation)
-	  (progn
-	    (while (looking-at citation)
-	      (forward-line)
-	      (move-to-column depth))
-	    (let ((overlay (make-overlay beg-sub (point)))
-                  (invis-spec (make-symbol "notmuch-citation-region")))
-              (add-to-invisibility-spec invis-spec)
-	      (overlay-put overlay 'invisible invis-spec)
-              (let ((p (point-marker))
-                    (cite-button-text
-                     (concat "["  (number-to-string (count-lines beg-sub (point)))
-                             "-line citation. Click/Enter to show.]")))
-                (goto-char (- beg-sub 1))
-                (insert (concat "\n" indent))
-                (insert-button cite-button-text
-                               'invisibility-spec invis-spec
-                               :type 'notmuch-button-citation-toggle-type)
-                (forward-line)
-              ))))
-      (move-to-column depth)
-      (if (looking-at notmuch-show-signature-regexp)
-	  (let ((sig-lines (- (count-lines beg-sub end) 1)))
-	    (if (<= sig-lines notmuch-show-signature-lines-max)
-		(progn
-                  (let ((invis-spec (make-symbol "notmuch-signature-region")))
-                    (add-to-invisibility-spec invis-spec)
-                    (overlay-put (make-overlay beg-sub end)
-                                 'invisible invis-spec)
-                  
-                    (goto-char (- beg-sub 1))
-                    (insert (concat "\n" indent))
-                    (let ((sig-button-text (concat "[" (number-to-string sig-lines)
-                                                   "-line signature. Click/Enter to show.]")))
-                      (insert-button sig-button-text 'invisibility-spec invis-spec
-                                     :type 'notmuch-button-signature-toggle-type)
-                     )
-                    (insert "\n")
-                    (goto-char end))))))
-      (forward-line))))
+  "Markup citations, and up to one signature in the given region"
+  ;; it would be nice if the untabify was not required, but 
+  ;; that would require notmuch to indent with spaces.
+  (untabify beg end)
+  (let ((citation-regexp (notmuch-show-citation-regexp depth))
+	(signature-regexp (concat (format "^[[:space:]]\\{%d\\}" depth) 
+				  notmuch-show-signature-regexp))
+	(original-regexp (concat (format "^[[:space:]]\\{%d\\}" depth) 
+				  notmuch-show-original-regexp))
+
+	(indent (concat "\n" (make-string depth ? ))))
+    (goto-char beg)
+    (beginning-of-line)
+
+    (if (and (< (point) end) 
+	     (re-search-forward original-regexp end t))
+	(let* ((msg-start (match-beginning 0))
+	       (msg-lines (1- (count-lines msg-start end))))
+	  (notmuch-show-region-to-button 
+	   msg-start
+	   end
+	   "original"
+	   indent
+	   (format notmuch-show-original-button-format msg-lines)
+	   )))
+
+    (while (and (< (point) end) 
+		(re-search-forward citation-regexp end t))
+      (let* ((cite-start (match-beginning 0))
+	     (cite-end 	(match-end 0))
+	     (cite-lines (count-lines cite-start cite-end)))
+	(when (>  cite-lines (1+ notmuch-show-citation-lines-prefix))
+	    (goto-char cite-start)
+	    (forward-line notmuch-show-citation-lines-prefix)
+	    (notmuch-show-region-to-button 
+	     (point) cite-end
+	     "citation"
+	     indent
+	     (format notmuch-show-citation-button-format 
+		     (- cite-lines notmuch-show-citation-lines-prefix))
+	     ))))
+
+    (if (and (< (point) end) 
+	     (re-search-forward signature-regexp end t))
+	(let* ((sig-start (match-beginning 0))
+	       (sig-lines (1- (count-lines sig-start end))))
+	  (if (<= sig-lines notmuch-show-signature-lines-max)
+	      (notmuch-show-region-to-button 
+	       sig-start
+	       end
+	       "signature"
+	       indent
+	       (format notmuch-show-signature-button-format sig-lines)
+	       ))))))
 
 (defun notmuch-show-markup-part (beg end depth)
   (if (re-search-forward notmuch-show-part-begin-regexp nil t)
-- 
1.6.5



More information about the notmuch mailing list