diff --git a/NEWS.org b/NEWS.org index 408b123d..b3eee0ca 100644 --- a/NEWS.org +++ b/NEWS.org @@ -16,6 +16,8 @@ - Honor ~truncate-string-ellipsis~ so you can now use 'fancy' ellipses for truncated strings with ~(setq truncate-string-ellipsis "…")~ + - Add some more properties for use in capturing org-mode links to messages / + queries. See [[info:mu4e#Org-mode links][the mu4e manual]] for details. * 1.4 (released, as of April 18 2020) diff --git a/mu4e/mu4e-org.el b/mu4e/mu4e-org.el index cb0a80a6..6942bc39 100644 --- a/mu4e/mu4e-org.el +++ b/mu4e/mu4e-org.el @@ -24,7 +24,7 @@ ;;; Commentary: -;; The expect version here is org 8.x. +;; The expect version here is org 9.x. ;;; Code: @@ -39,76 +39,48 @@ "Prefer linking to the query rather than to the message. If non-nil, `org-store-link' in `mu4e-headers-mode' links to the the current query; otherwise, it links to the message at point.") -(define-obsolete-variable-alias 'org-mu4e-link-query-in-headers-mode - 'mu4e-org-link-query-in-headers-mode "1.3.6") - -(defcustom mu4e-org-link-desc-func - (lambda (msg) (or (plist-get msg :subject) "No subject")) - "Function that takes a msg and returns a description. -This can be use in org capture templates. - -Example usage: - - (defun my-link-descr (msg) - (let ((subject (or (plist-get msg :subject) - \"No subject\")) - (date (or (format-time-string mu4e-headers-date-format - (mu4e-msg-field msg :date)) - \"No date\"))) - (concat subject \" \" date))) - - (setq org-mu4e-link-desc-func 'my-link-descr)" - :type 'function - :group 'org-mu4e) -(define-obsolete-variable-alias 'org-mu4e-link-desc-func - 'mu4e-org-link-desc-func "1.3.6") (defun mu4e~org-store-link-query () "Store a link to a mu4e query." - (let* ((query (mu4e-last-query)) - (date (format-time-string (org-time-stamp-format))) - ;; seems we get an error when there's no date... - (link (concat "mu4e:query:" query))) - (org-store-link-props - :type "mu4e" - :query query - :date date) - (org-add-link-props - :link link - :description (format "mu4e-query: '%s'" query)) - link)) + (setq org-store-link-plist nil) ; reset + (org-store-link-props + :type "mu4e" + :query (mu4e-last-query) + :date (format-time-string "%FT%T") ;; avoid error + :link (link (concat "mu4e:query:" query)) + :description (format "[%s]" query))) -(defun mu4e~org-first-address (msg field) +(defun mu4e~org-address (cell) "Get address field FIELD from MSG as a string or nil." - (let* ((val (plist-get msg field)) - (name (when val (car (car val)))) - (addr (when val (cdr (car val))))) - (when val - (if name - (format "%s <%s>" name addr) - (format "%s" addr))))) + (let ((name (car cell)) (addr (cdr cell))) + (if name + (format "%s <%s>" name addr) + (format "%s" addr)))) (defun mu4e~org-store-link-message () "Store a link to a mu4e message." (unless (fboundp 'mu4e-message-at-point) (error "Please load mu4e before mu4e-org")) + (setq org-store-link-plist nil) (let* ((msg (mu4e-message-at-point)) - (msgid (or (plist-get msg :message-id) "")) - (date (plist-get msg :date)) - (date (format-time-string (org-time-stamp-format) date)) - ;; seems we get an error when there's no date... - (link (concat "mu4e:msgid:" msgid))) + (from (car-safe (plist-get msg :from))) + (to (car-safe (plist-get msg :to))) + (date (format-time-string "%FT%T" (plist-get msg :date))) + (msgid (or (plist-get msg :message-id) + (mu4e-error "Cannot link message without message-id")))) (org-store-link-props - :type "mu4e" - :message-id msgid - :to (mu4e~org-first-address msg :to) - :from (mu4e~org-first-address msg :from) - :date date - :subject (plist-get msg :subject)) - (org-add-link-props - :link link - :description (funcall mu4e-org-link-desc-func msg)) - link)) + :type "mu4e" + :date date + :from (when from + (mu4e~org-address from)) + :maildir (plist-get msg :maildir) + :message-id msgid + :path (plist-get msg :path) + :subject (plist-get msg :subject) + :to (when to + (mu4e~org-address to)) + :link (concat "mu4e:msgid:" msgid) + :description (or (plist-get msg :subject) "No subject")))) (defun mu4e-org-store-link () "Store a link to a mu4e message or query. @@ -123,16 +95,7 @@ valid even after moving the message around." (mu4e~org-store-link-query) (when (mu4e-message-at-point t) (mu4e~org-store-link-message)))) - -;; org-add-link-type is obsolete as of org-mode 9. Instead we will use the -;; org-link-set-parameters method -(if (fboundp 'org-link-set-parameters) - (org-link-set-parameters "mu4e" - :follow #'mu4e-org-open - :store #'mu4e-org-store-link) - (org-add-link-type "mu4e" 'mu4e-org-open) - (add-hook 'org-store-link-functions 'mu4e-org-store-link)) - + ; (defun mu4e-org-open (link) "Open the org LINK. Open the mu4e message (for links starting with 'msgid:') or run @@ -155,8 +118,10 @@ it with org)." (call-interactively 'org-store-link) (org-capture)) -(make-obsolete 'org-mu4e-store-and-capture 'org-mu4e-store-and-capture "1.3.6") -;;; _ +;; install mu4e-link support. +(org-link-set-parameters "mu4e" + :follow #'mu4e-org-open + :store #'mu4e-org-store-link) (provide 'mu4e-org) ;;; mu4e-org.el ends here diff --git a/mu4e/mu4e.texi b/mu4e/mu4e.texi index c1a7f5fc..ab7f4697 100644 --- a/mu4e/mu4e.texi +++ b/mu4e/mu4e.texi @@ -3230,9 +3230,9 @@ you can do so by adding the following to your configuration: @node Org-mode links @section Org-mode links -It can be useful to include links to e-mail messages or even search -queries in your org-mode files. @t{mu4e} supports this by default, -unless you set @t{mu4e-support-org} to @code{nil}. +It can be useful to include links to e-mail messages or search queries +in your org-mode files. @t{mu4e} supports this by default, unless you +set @t{mu4e-support-org} to @code{nil}. You can use the normal @t{org-mode} mechanisms to store links: @kbd{M-x org-store-link} stores a link to a particular message when @@ -3242,34 +3242,53 @@ you are in @ref{Message view}. When you are in @ref{Headers view}, the particular message otherwise (which is the default). You can insert this link later with @kbd{M-x org-insert-link}. From -@t{org-mode}, you can go to the query or message the link points to with -either @kbd{M-x org-agenda-open-link} in agenda buffers, or @kbd{M-x -org-open-at-point} elsewhere --- both typically bound to @kbd{C-c C-o}. +@t{org-mode}, you can go to the query or message the link points to +with either @kbd{M-x org-agenda-open-link} in agenda buffers, or +@kbd{M-x org-open-at-point} elsewhere --- both typically bound to +@kbd{C-c C-o}. You can also directly @emph{capture} such links --- for example, to -add e-mail messages to your todo-list. For that, @t{org-mu4e} has a +add e-mail messages to your todo-list. For that, @t{mu4e-org} has a function @code{mu4e-org-store-and-capture}. This captures the message-at-point (or header --- see the discussion on @code{mu4e-org-link-query-in-headers-mode} above), then calls @t{org-mode}'s capture functionality. -You can add some specific capture-template for this: for example, to add -a message to your todo-list, and set a deadline for processing it within -two days, you could add this to @code{org-capture-templates}: +You can add some specific capture-template for this. In your capture +templates, the following mu4e-specific values are available: + +@cartouche +@verbatim +item | description +-----------------------------------------------------+------------------------ +%:date, %:date-timestamp, %d:date-timestamp-inactive | date, org timestamps +%:from, %:fromname, %:fromaddress | sender, name/address +%:to, %:toname, %:toaddress | recipient, name/address +%:maildir | maildir for the message +%:message-id | message-id +%:path | file system path +%:subject | message subject +@end verbatim +@end cartouche + +For example, to add a message to your todo-list, and set a deadline +for processing it within two days, you could add this to +@code{org-capture-templates}: @lisp ("P" "process-soon" entry (file+headline "todo.org" "Todo") - "* TODO %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))") + "* TODO %:fromname: %a %?\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+2d\"))") @end lisp -If you use the functionality a lot, you may want to define key-bindings -for that in headers and view mode: +If you use the functionality a lot, you may want to define +key-bindings for that in headers and view mode: @lisp (define-key mu4e-headers-mode-map (kbd "C-c c") 'org-mu4e-store-and-capture) (define-key mu4e-view-mode-map (kbd "C-c c") 'org-mu4e-store-and-capture) @end lisp + @node Org-contacts @section Org-contacts