X-Git-Url: https://git.notmuchmail.org/git?p=notmuch;a=blobdiff_plain;f=notmuch.el;h=8894a8e194716f444489b1676c3630c545c82c95;hp=872397646857956e1a8f67db2077e689a6f704a3;hb=dac31c9e01a18130f141994c98a48800cdb03efa;hpb=8561c7463a5de3bd0990d8244abb1c67ca4f4a7d diff --git a/notmuch.el b/notmuch.el index 87239764..8894a8e1 100644 --- a/notmuch.el +++ b/notmuch.el @@ -19,7 +19,8 @@ ; ; Authors: Carl Worth -(load "cl-seq") +(require 'cl) +(require 'mm-view) (defvar notmuch-show-mode-map (let ((map (make-sparse-keymap))) @@ -35,6 +36,7 @@ (define-key map "b" 'notmuch-show-toggle-body-read-visible) (define-key map "c" 'notmuch-show-toggle-citations-visible) (define-key map "h" 'notmuch-show-toggle-headers-visible) + (define-key map "m" 'message-mail) (define-key map "n" 'notmuch-show-next-message) (define-key map "N" 'notmuch-show-mark-read-then-next-open-message) (define-key map "p" 'notmuch-show-previous-message) @@ -43,6 +45,7 @@ (define-key map "q" 'kill-this-buffer) (define-key map "r" 'notmuch-show-reply) (define-key map "s" 'notmuch-show-toggle-signatures-visible) + (define-key map "v" 'notmuch-show-view-all-mime-parts) (define-key map "w" 'notmuch-show-view-raw-message) (define-key map "x" 'kill-this-buffer) (define-key map "+" 'notmuch-show-add-tag) @@ -54,7 +57,17 @@ "Keymap for \"notmuch show\" buffers.") (fset 'notmuch-show-mode-map notmuch-show-mode-map) -(defvar notmuch-show-signature-lines-max 6 +(defvar notmuch-show-signature-regexp "\\(-- ?\\|_+\\)$" + "Pattern to match a line that separates content from signature. + +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).") + +(defvar notmuch-show-signature-lines-max 12 "Maximum length of signature that will be hidden by default.") (set 'notmuch-show-message-begin-regexp " message{") @@ -70,6 +83,7 @@ (set 'notmuch-show-marker-regexp " \\(message\\|header\\|body\\|attachment\\|part\\)[{}].*$") (set 'notmuch-show-id-regexp "\\(id:[^ ]*\\)") +(set 'notmuch-show-depth-regexp " depth:\\([0-9]*\\) ") (set 'notmuch-show-filename-regexp "filename:\\(.*\\)$") (set 'notmuch-show-tags-regexp "(\\([^)]*\\))$") @@ -222,6 +236,18 @@ buffer." (interactive) (view-file (notmuch-show-get-filename))) +(defun notmuch-show-view-all-mime-parts () + "Use external viewers (according to mailcap) to view all MIME-encoded parts." + (interactive) + (save-excursion + (let ((filename (notmuch-show-get-filename))) + (switch-to-buffer (generate-new-buffer (concat "*notmuch-mime-" + filename + "*"))) + (insert-file-contents filename nil nil nil t) + (mm-display-parts (mm-dissect-buffer)) + (kill-this-buffer)))) + (defun notmuch-show-reply () "Begin composing a reply to the current message in a new buffer." (interactive) @@ -410,65 +436,103 @@ which this thread was originally shown." (if last (notmuch-show-archive-thread)))))) -(defun notmuch-show-markup-citations-region (beg end) +(defun notmuch-show-markup-citations-region (beg end depth) (goto-char beg) (beginning-of-line) (while (< (point) end) - (let ((beg-sub (point))) - (if (looking-at ">") + (let ((beg-sub (point-marker)) + (indent (make-string depth ? )) + (citation "[[:space:]]*>")) + (if (looking-at citation) (progn - (while (looking-at ">") + (while (looking-at citation) (forward-line)) (let ((overlay (make-overlay beg-sub (point)))) (overlay-put overlay 'invisible 'notmuch-show-citation) (overlay-put overlay 'before-string - (concat "[" (number-to-string (count-lines beg-sub (point))) + (concat indent + "[" (number-to-string (count-lines beg-sub (point))) "-line citation. Press 'c' to show.]\n"))))) - (if (looking-at "--[ ]?$") - (let ((sig-lines (count-lines beg-sub end))) + (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 - (overlay-put (make-overlay beg-sub (+ beg-sub 1)) - 'before-string - (concat "[" (number-to-string sig-lines) - "-line signature. Press 's' to show.]")) - (overlay-put (make-overlay (+ beg-sub 2) end) + (overlay-put (make-overlay beg-sub end) 'invisible 'notmuch-show-signature) + (overlay-put (make-overlay beg (- beg-sub 1)) + 'after-string + (concat "\n" indent + "[" (number-to-string sig-lines) + "-line signature. Press 's' to show.]")) (goto-char end))))) (forward-line)))) -(defun notmuch-show-markup-body () +(defun notmuch-show-markup-part (beg end depth) + (if (re-search-forward notmuch-show-part-begin-regexp nil t) + (progn + (forward-line) + (let ((beg (point-marker))) + (re-search-forward notmuch-show-part-end-regexp) + (let ((end (copy-marker (match-beginning 0)))) + (goto-char end) + (if (not (bolp)) + (insert "\n")) + (indent-rigidly beg end depth) + (notmuch-show-markup-citations-region beg end depth) + ; Advance to the next part (if any) (so the outer loop can + ; determine whether we've left the current message. + (if (re-search-forward notmuch-show-part-begin-regexp nil t) + (beginning-of-line))))) + (goto-char end))) + +(defun notmuch-show-markup-parts-region (beg end depth) + (save-excursion + (goto-char beg) + (while (< (point) end) + (notmuch-show-markup-part beg end depth)))) + +(defun notmuch-show-markup-body (depth) (re-search-forward notmuch-show-body-begin-regexp) - (next-line 1) - (beginning-of-line) - (let ((beg (point))) + (forward-line) + (let ((beg (point-marker))) (re-search-forward notmuch-show-body-end-regexp) - (let ((end (match-beginning 0))) - (notmuch-show-markup-citations-region beg end) + (let ((end (copy-marker (match-beginning 0)))) + (notmuch-show-markup-parts-region beg end depth) (if (not (notmuch-show-message-unread-p)) (overlay-put (make-overlay beg end) - 'invisible 'notmuch-show-body-read))))) + 'invisible 'notmuch-show-body-read)) + (set-marker beg nil) + (set-marker end nil) + ))) -(defun notmuch-show-markup-header () +(defun notmuch-show-markup-header (depth) (re-search-forward notmuch-show-header-begin-regexp) - (forward-line 1) - (beginning-of-line) - (let ((beg (point))) + (forward-line) + (let ((beg (point-marker))) (end-of-line) ; Inverse video for subject (overlay-put (make-overlay beg (point)) 'face '((cons :inverse-video t))) - (beginning-of-line) (forward-line 2) - (set 'beg (point)) - (re-search-forward notmuch-show-header-end-regexp) - (overlay-put (make-overlay beg (match-beginning 0)) - 'invisible 'notmuch-show-header))) + (let ((beg-hidden (point-marker))) + (re-search-forward notmuch-show-header-end-regexp) + (beginning-of-line) + (let ((end (point-marker))) + (indent-rigidly beg end depth) + (overlay-put (make-overlay beg-hidden end) + 'invisible 'notmuch-show-header) + (set-marker beg nil) + (set-marker beg-hidden nil) + (set-marker end nil) + )))) (defun notmuch-show-markup-message () (if (re-search-forward notmuch-show-message-begin-regexp nil t) (progn - (notmuch-show-markup-header) - (notmuch-show-markup-body)) + (re-search-forward notmuch-show-depth-regexp) + (let ((depth (string-to-number (buffer-substring (match-beginning 1) (match-end 1))))) + (notmuch-show-markup-header depth) + (notmuch-show-markup-body depth))) (goto-char (point-max)))) (defun notmuch-show-hide-markers () @@ -609,11 +673,15 @@ thread from that buffer can be show when done with this one)." (notmuch-show-toggle-body-read-visible))))) ))) +(defvar notmuch-search-authors-width 40 + "Number of columns to use to diplay authors in a notmuch-search buffer.") + (defvar notmuch-search-mode-map (let ((map (make-sparse-keymap))) (define-key map "a" 'notmuch-search-archive-thread) (define-key map "b" 'notmuch-search-scroll-down) (define-key map "f" 'notmuch-search-filter) + (define-key map "m" 'message-mail) (define-key map "n" 'next-line) (define-key map "o" 'notmuch-search-toggle-order) (define-key map "p" 'previous-line) @@ -706,14 +774,24 @@ global search. (if (re-search-forward "thread:[a-fA-F0-9]*" nil t) (progn (forward-char) - (overlay-put (make-overlay beg (point)) 'invisible 'notmuch-search))))) + (overlay-put (make-overlay beg (point)) 'invisible 'notmuch-search) + (re-search-forward ".*\\[[0-9]*/[0-9]*\\] \\([^;]*\\)\\(;\\)") + (let* ((authors (buffer-substring (match-beginning 1) (match-end 1))) + (authors-length (length authors))) + ;; Drop the semi-colon + (replace-match "" t nil nil 2) + (if (<= authors-length notmuch-search-authors-width) + (replace-match (concat authors (make-string + (- notmuch-search-authors-width + authors-length) ? )) t t nil 1) + (replace-match (concat (substring authors 0 (- notmuch-search-authors-width 3)) "...") t t nil 1))))))) (defun notmuch-search-markup-thread-ids () (save-excursion (goto-char (point-min)) (while (not (eobp)) (notmuch-search-markup-this-thread-id) - (next-line)))) + (forward-line)))) (defun notmuch-search-show-thread () (interactive)