Commit 43f0674679a7
Changed files (1)
dots
.config
emacs
dots/.config/emacs/init.el
@@ -1912,21 +1912,52 @@ minibuffer, even without explicitly focusing it."
(add-to-list 'org-capture-templates
`("m" "✉ Email Workflow")
t)
+ ;; Forward declaration - defined in mu4e config
+ (declare-function vde-mu4e--body-summary-for-capture "init")
(add-to-list 'org-capture-templates
`("mf" "Follow Up" entry
(file ,org-inbox-file)
- "* TODO Follow up with %:from on %a\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%i"
+ "* TODO Follow up: %:subject :email:
+:PROPERTIES:
+:CREATED:\t%U
+:FROM:\t%:from
+:DATE:\t%:date
+:END:
+SCHEDULED:%t
+DEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))
+%(vde-mu4e--body-summary-for-capture)
+%i
+Link: %a"
:immediate-finish t)
t)
(add-to-list 'org-capture-templates
`("mr" "Read Later" entry
(file ,org-inbox-file)
- "* TODO Read %:subject\nSCHEDULED:%t\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))\n\n%a\n\n%i" :immediate-finish t)
+ "* TODO Read: %:subject :email:
+:PROPERTIES:
+:CREATED:\t%U
+:FROM:\t%:from
+:DATE:\t%:date
+:END:
+SCHEDULED:%t
+DEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))
+%(vde-mu4e--body-summary-for-capture)
+%i
+Link: %a"
+ :immediate-finish t)
t)
(add-to-list 'org-capture-templates
`("mt" "Task from email" entry
(file ,org-inbox-file)
- "* TODO %:subject :email:\n:PROPERTIES:\n:CREATED:\t%U\n:END:\n\nFrom: %:from\nEmail: %a\n\n%?"
+ "* TODO %:subject :email:
+:PROPERTIES:
+:CREATED:\t%U
+:FROM:\t%:from
+:DATE:\t%:date
+:END:
+%(vde-mu4e--body-summary-for-capture)
+%?
+Link: %a"
:empty-lines 1)
t)
@@ -2216,6 +2247,78 @@ Add this function to the `after-save-hook'."
message-sendmail-extra-arguments '("--read-envelope-from")
message-send-mail-function 'message-send-mail-with-sendmail)
+ (defun vde-mu4e--extract-body-summary (&optional max-lines)
+ "Extract a summary from the current mu4e message body.
+Returns the first MAX-LINES lines (default 10) of the plain text body,
+with quoted lines and signatures removed."
+ (let ((max-lines (or max-lines 10))
+ (msg (mu4e-message-at-point 'noerror)))
+ (if (not msg)
+ ""
+ (let* ((path (mu4e-message-field msg :path))
+ (body-txt (when (and path (file-exists-p path))
+ (with-temp-buffer
+ (insert-file-contents path)
+ (goto-char (point-min))
+ ;; Skip headers - find empty line
+ (when (re-search-forward "^$" nil t)
+ (forward-line 1)
+ (buffer-substring-no-properties (point) (point-max)))))))
+ (if (not body-txt)
+ ""
+ ;; Clean up the body
+ (with-temp-buffer
+ (insert body-txt)
+ ;; Try to decode if it looks like quoted-printable
+ (goto-char (point-min))
+ (when (re-search-forward "Content-Transfer-Encoding: quoted-printable" nil t)
+ (goto-char (point-min))
+ (when (re-search-forward "^$" nil t)
+ (forward-line 1)
+ (ignore-errors
+ (quoted-printable-decode-region (point) (point-max)))))
+ ;; Remove MIME boundaries and headers
+ (goto-char (point-min))
+ (while (re-search-forward "^--.*$\\|^Content-Type:.*$\\|^Content-Transfer-Encoding:.*$" nil t)
+ (replace-match ""))
+ ;; Remove HTML tags if present
+ (goto-char (point-min))
+ (while (re-search-forward "<[^>]+>" nil t)
+ (replace-match ""))
+ ;; Remove quoted lines (starting with >)
+ (goto-char (point-min))
+ (while (re-search-forward "^>.*$" nil t)
+ (replace-match ""))
+ ;; Remove signature (everything after -- )
+ (goto-char (point-min))
+ (when (re-search-forward "^-- $" nil t)
+ (delete-region (match-beginning 0) (point-max)))
+ ;; Remove excessive whitespace
+ (goto-char (point-min))
+ (while (re-search-forward "^[ \t]*\n\\([ \t]*\n\\)+" nil t)
+ (replace-match "\n"))
+ ;; Get first N non-empty lines
+ (goto-char (point-min))
+ (let ((lines nil)
+ (count 0))
+ (while (and (< count max-lines) (not (eobp)))
+ (let ((line (string-trim (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))))
+ (when (and (> (length line) 0)
+ (not (string-match-p "^\\s-*$" line)))
+ (push line lines)
+ (setq count (1+ count))))
+ (forward-line 1))
+ (string-join (nreverse lines) "\n"))))))))
+
+ (defun vde-mu4e--body-summary-for-capture ()
+ "Return email body summary for org-capture template."
+ (let ((summary (vde-mu4e--extract-body-summary 8)))
+ (if (string-empty-p summary)
+ ""
+ (concat "\n#+begin_quote\n" summary "\n#+end_quote"))))
+
(defun vde-mu4e--mark-get-copy-target ()
"Ask for a copy target, and propose to create it if it does not exist."
(let* ((target (mu4e-ask-maildir "Copy message to: "))