mirror of https://github.com/djcb/mu.git
* add support for org-mode links to messages/queries
- org-mu4e.el: add "mu4e:"-link type and handlers to org-mode - Makefile.am: add org-mu4e.el to package - mu4e-hdrs.el: register handler functions for server data *outside* header mode, so they can be used independently (and we can link to messages even when mu4e is not active already) - mu4e-view.el, mu-server.1, mu-proc.el, mu-cmd-server.c: support viewing messages by msgid (rather than only by docid); document it
This commit is contained in:
parent
e4d5d6de8a
commit
4dbb05f33c
|
@ -1,4 +1,4 @@
|
|||
## Copyright (C) 2008-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
## Copyright (C) 2008-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
|
@ -35,6 +35,7 @@ elisp_DATA= \
|
|||
mu4e-view.el \
|
||||
mu4e-proc.el \
|
||||
mu4e-send.el \
|
||||
mu4e-version.el
|
||||
mu4e-version.el \
|
||||
org-mu4e.el
|
||||
|
||||
EXTRA_DIST=$(elisp_DATA)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
;; mu4e-hdrs.el -- part of mm, the mu mail user agent
|
||||
;; mu4e-hdrs.el -- part of mu4e, the mu mail user agent
|
||||
;;
|
||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Keywords: email
|
||||
;; Version: 0.0
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
|
@ -28,8 +26,6 @@
|
|||
;; descriptions of emails, aka 'headers' (not to be confused with headers like
|
||||
;; 'To:' or 'Subject:')
|
||||
|
||||
;; mm
|
||||
|
||||
;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
@ -39,7 +35,6 @@
|
|||
;;;; internal variables/constants ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defvar mu4e-last-expr nil
|
||||
"*internal* The most recent search expression.")
|
||||
|
||||
|
||||
(defconst mu4e-hdrs-buffer-name "*mu4e-headers*"
|
||||
"*internal* Name of the buffer for message headers.")
|
||||
|
@ -322,6 +317,15 @@ after the end of the search results."
|
|||
|
||||
(fset 'mu4e-hdrs-mode-map mu4e-hdrs-mode-map)
|
||||
|
||||
;; we register our handler functions for the mu4e-proc (mu server) output
|
||||
(setq mu4e-proc-error-func 'mu4e-hdrs-error-handler)
|
||||
(setq mu4e-proc-update-func 'mu4e-hdrs-update-handler)
|
||||
(setq mu4e-proc-header-func 'mu4e-hdrs-header-handler)
|
||||
(setq mu4e-proc-found-func 'mu4e-hdrs-found-handler)
|
||||
(setq mu4e-proc-view-func 'mu4e-hdrs-view-handler)
|
||||
(setq mu4e-proc-remove-func 'mu4e-hdrs-remove-handler)
|
||||
;; this last one is defined in mu4e-send.el
|
||||
(setq mu4e-proc-compose-func 'mu4e-send-compose-handler)
|
||||
|
||||
(defun mu4e-hdrs-mode ()
|
||||
"Major mode for displaying mua search results."
|
||||
|
@ -336,16 +340,6 @@ after the end of the search results."
|
|||
(make-local-variable 'mu4e-msg-map)
|
||||
(make-local-variable 'mu4e-thread-info-map)
|
||||
|
||||
;; we register our handler functions for the mu4e-proc (mu server) output
|
||||
(setq mu4e-proc-error-func 'mu4e-hdrs-error-handler)
|
||||
(setq mu4e-proc-update-func 'mu4e-hdrs-update-handler)
|
||||
(setq mu4e-proc-header-func 'mu4e-hdrs-header-handler)
|
||||
(setq mu4e-proc-found-func 'mu4e-hdrs-found-handler)
|
||||
(setq mu4e-proc-view-func 'mu4e-hdrs-view-handler)
|
||||
(setq mu4e-proc-remove-func 'mu4e-hdrs-remove-handler)
|
||||
;; this last one is defined in mu4e-send.el
|
||||
(setq mu4e-proc-compose-func 'mu4e-send-compose-handler)
|
||||
|
||||
(setq
|
||||
mu4e-marks-map (make-hash-table :size 16 :rehash-size 2)
|
||||
mu4e-msg-map (make-hash-table :size 1024 :rehash-size 2 :weakness nil)
|
||||
|
@ -356,7 +350,7 @@ after the end of the search results."
|
|||
buffer-undo-list t ;; don't record undo information
|
||||
buffer-read-only t
|
||||
overwrite-mode 'overwrite-mode-binary)
|
||||
|
||||
|
||||
(setq header-line-format
|
||||
(cons
|
||||
(make-string (floor (fringe-columns 'left t)) ?\s)
|
||||
|
@ -583,6 +577,7 @@ work well."
|
|||
(unless docid (error "No message at point."))
|
||||
(mu4e-proc-view-msg docid)))
|
||||
|
||||
|
||||
(defun mu4e-hdrs-compose (compose-type)
|
||||
"Compose either a reply/forward based on the message at point. or
|
||||
start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
||||
|
@ -619,12 +614,10 @@ start editing it. COMPOSE-TYPE is either `reply', `forward' or
|
|||
(defun mu4e-ignore-marks ()
|
||||
"If there are still marks in the header list, warn the user."
|
||||
(if mu4e-marks-map
|
||||
(let*
|
||||
((num
|
||||
(hash-table-count mu4e-marks-map))
|
||||
(unmark (or (= 0 num)
|
||||
(y-or-n-p
|
||||
(format "Sure you want to unmark %d message(s)?" num)))))
|
||||
(let* ((num (hash-table-count mu4e-marks-map))
|
||||
(unmark (or (= 0 num)
|
||||
(y-or-n-p
|
||||
(format "Sure you want to unmark %d message(s)?" num)))))
|
||||
(message nil)
|
||||
unmark))
|
||||
t)
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
;;; mu4e-proc.el -- part of mm, the mu mail user agent
|
||||
;;; mu4e-proc.el -- part of mu4e, the mu mail user agent
|
||||
;;
|
||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Keywords: email
|
||||
;; Version: 0.0
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
|
@ -418,10 +416,12 @@ set to e.g. '/drafts'; if this works, we will receive (:info :path
|
|||
response."
|
||||
(mu4e-proc-send-command "ping"))
|
||||
|
||||
(defun mu4e-proc-view-msg (docid)
|
||||
"Get one particular message based on its DOCID. The result will
|
||||
(defun mu4e-proc-view-msg (docid-or-msgid)
|
||||
"Get one particular message based on its DOCID-OR-MSGID. The result will
|
||||
be delivered to the function registered as `mu4e-proc-message-func'."
|
||||
(mu4e-proc-send-command "view %d" docid))
|
||||
(if (stringp docid-or-msgid)
|
||||
(mu4e-proc-send-command "view %s" docid-or-msgid)
|
||||
(mu4e-proc-send-command "view %d" docid-or-msgid)))
|
||||
|
||||
(defun mu4e-proc-compose (compose-type docid)
|
||||
"Start composing a message with DOCID and COMPOSE-TYPE (a symbol,
|
||||
|
@ -452,5 +452,6 @@ and update the database afterwards."
|
|||
(with-current-buffer buf
|
||||
(kill-buffer-and-window))))
|
||||
|
||||
|
||||
(provide 'mu4e-proc)
|
||||
|
||||
;; End of mu4e-proc.el
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
;; mu4e-view.el -- part of mu4e, the mu mail user agent
|
||||
;;
|
||||
;; Copyright (C) 2011 Dirk-Jan C. Binnema
|
||||
;; Copyright (C) 2011-2012 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Keywords: email
|
||||
;; Version: 0.0
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
|
@ -49,6 +47,12 @@
|
|||
(defvar mu4e-current-msg nil
|
||||
"*internal* The plist describing the current message.")
|
||||
|
||||
(defun mu4e-view-message-with-msgid (msgid)
|
||||
"View message with MSGID. This is meant for external programs
|
||||
wanting to show specific messages - for example, `mu4e-org'."
|
||||
(mu4e-proc-view-msg msgid))
|
||||
|
||||
|
||||
(defun mu4e-view (msg hdrsbuf &optional update)
|
||||
"Display the message MSG in a new buffer, and keep in sync with HDRSBUF.
|
||||
'In sync' here means that moving to the next/previous message in
|
||||
|
@ -118,7 +122,7 @@ marking if it still had that."
|
|||
|
||||
(mu4e-mark-footer)
|
||||
(mu4e-make-urls-clickable)
|
||||
|
||||
|
||||
(unless update
|
||||
(mu4e-view-mark-as-read-maybe)))))
|
||||
|
||||
|
@ -387,7 +391,7 @@ Seen; if the message is not New/Unread, do nothing."
|
|||
(lexical-let ((url url))
|
||||
(lambda ()
|
||||
(interactive)
|
||||
(browse-url url))))
|
||||
(browse-url url))))
|
||||
|
||||
|
||||
|
||||
|
@ -411,7 +415,7 @@ number them so they can be opened using `mu4e-view-go-to-url'."
|
|||
(replace-match (concat url
|
||||
(propertize (format "[%d]" num)
|
||||
'face 'mu4e-view-url-number-face))))))))
|
||||
|
||||
|
||||
|
||||
;; raw mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
@ -506,37 +510,34 @@ number them so they can be opened using `mu4e-view-go-to-url'."
|
|||
|
||||
;; functions for org-contacts
|
||||
|
||||
(defun mu4e-org-contacts-from (name-or-email)
|
||||
"Get a message field if we are in view mode; NAME-OR-EMAIL should
|
||||
be either 'name or 'email to get the corresponding field. If the
|
||||
field is not found, \"\" is returned. Use this with org-contact
|
||||
with a template like:
|
||||
(defun mu4e-view-snarf-from (name-or-email)
|
||||
"Get the From:-data for the current message; NAME-OR-EMAIL should
|
||||
be a symbol 'name or 'email to get the corresponding field. If the
|
||||
field is not found, \"\" is returned.
|
||||
|
||||
You can use this with e.g. org-contact with a template like:
|
||||
(\"c\" \"Contacts\" entry (file \"~/Org/contacts.org\")
|
||||
\"* %(mu4e-org-contacts-from 'name)
|
||||
\"* %(mu4e-view-snarf-from 'name)
|
||||
:PROPERTIES:
|
||||
:EMAIL: %(mu4e-org-contacts-from 'email)
|
||||
:EMAIL: %(mu4e-view-snarf-from 'email)
|
||||
:END:\")))
|
||||
|
||||
See the `org-contacts' documentation for more details."
|
||||
(with-current-buffer mu4e-view-buffer-name ;; hackish...
|
||||
(unless (eq major-mode 'mu4e-view-mode)
|
||||
(error "Not in mu4e-view mode."))
|
||||
(unless mu4e-current-msg
|
||||
(error "No current message."))
|
||||
(let ((from (car-safe (plist-get mu4e-current-msg :from))))
|
||||
(cond
|
||||
((not from) "") ;; nothing found
|
||||
((eq name-or-email 'name)
|
||||
(or (car-safe from) ""))
|
||||
((eq name-or-email 'email)
|
||||
(or (cdr-safe from) ""))
|
||||
(t (error "Not supported: %S" name-or-email))))))
|
||||
(unless (eq major-mode 'mu4e-view-mode)
|
||||
(error "Not in mu4e-view mode."))
|
||||
(unless mu4e-current-msg
|
||||
(error "No current message."))
|
||||
(let ((from (car-safe (plist-get mu4e-current-msg :from))))
|
||||
(cond
|
||||
((not from) "") ;; nothing found
|
||||
((eq name-or-email 'name)
|
||||
(or (car-safe from) ""))
|
||||
((eq name-or-email 'email)
|
||||
(or (cdr-safe from) ""))
|
||||
(t (error "Not supported: %S" name-or-email)))))
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
;; Interactive functions
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
;;; org-mu4e -- Support for links to mu4e messages/queries from within org-mode
|
||||
;;
|
||||
;; Copyright (C) 2012 Dirk-Jan C. Binnema
|
||||
|
||||
;; Author: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Maintainer: Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
;; Keywords: outlines, hypermedia, calendar, mail
|
||||
;; Version: 0.0
|
||||
|
||||
;; This file is not part of GNU Emacs.
|
||||
;;
|
||||
;; GNU Emacs 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.
|
||||
|
||||
;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'org)
|
||||
(eval-when-compile (require 'cl))
|
||||
(eval-when-compile (require 'mu4e))
|
||||
|
||||
(defun org-mu4e-store-link ()
|
||||
"Store a link to a mu4e query or message."
|
||||
(cond
|
||||
;; storing links to queries
|
||||
((eq major-mode 'mu4e-hdrs-mode)
|
||||
(let* ((query mu4e-last-expr)
|
||||
desc link)
|
||||
(org-store-link-props :type "mu4e" :query query)
|
||||
(setq
|
||||
desc (org-make-link "mu4e:query:" query)
|
||||
link desc)
|
||||
(org-add-link-props :link link :description desc)
|
||||
link))
|
||||
|
||||
;; storing links to messages
|
||||
((eq major-mode 'mu4e-view-mode)
|
||||
(let* ((msg mu4e-current-msg)
|
||||
(msgid (or (plist-get msg :message-id) "<none>"))
|
||||
(subject (or (plist-get msg :subject) "No subject"))
|
||||
link)
|
||||
(org-store-link-props :type "mu4e" :link link
|
||||
:message-id msgid :subject subject)
|
||||
(setq link (org-make-link "mu4e:msgid:" msgid))
|
||||
(org-add-link-props :link link :description subject)
|
||||
link))))
|
||||
|
||||
(org-add-link-type "mu4e" 'org-mu4e-open)
|
||||
(add-hook 'org-store-link-functions 'org-mu4e-store-link)
|
||||
|
||||
(defun org-mu4e-open (path)
|
||||
"Open the mu4e message (for paths starting with 'msgid:') or run
|
||||
the query (for paths starting with 'query:')."
|
||||
(require 'mu4e)
|
||||
(cond
|
||||
((string-match "^msgid:\\(.+\\)" path)
|
||||
(mu4e-view-message-with-msgid (match-string 1 path)))
|
||||
((string-match "^query:\\(.+\\)" path)
|
||||
(mu4e-search (match-string 1 path)))
|
||||
(t (message "mu4e: unrecognized link type '%s'" path))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(provide 'org-mu4e)
|
||||
|
||||
;;; org-mu4e.el ends here
|
|
@ -1,8 +1,8 @@
|
|||
.TH MU-SERVER 1 "December 2011" "User Manuals"
|
||||
.TH MU-SERVER 1 "January 2012" "User Manuals"
|
||||
|
||||
.SH NAME
|
||||
|
||||
mu server \- the mu backend for the mm e-mail cleint
|
||||
mu server \- the mu backend for the mu4e e-mail cleint
|
||||
|
||||
.SH DESCRIPTION
|
||||
|
||||
|
@ -131,7 +131,7 @@ Using the \fBview\fR command, we can all information (including the body) of a
|
|||
particular e-mail message.
|
||||
|
||||
.nf
|
||||
-> view <docid>
|
||||
-> view <docid-or-msgid>
|
||||
<- (:view <s-exp>)
|
||||
.fi
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||
/*
|
||||
** Copyright (C) 2010-2011 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2011-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
|
@ -441,8 +441,6 @@ get_docid_from_msgid (MuQuery *query, const char *str, GError **err)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* the string contains either a number (docid) or a message-id if it
|
||||
* doesn't look like a number, and the query param is non-nil, try to
|
||||
* locale the message with message-id in the database, and return its
|
||||
|
@ -720,15 +718,15 @@ cmd_open (MuStore *store, GSList *args, GError **err)
|
|||
|
||||
|
||||
static MuError
|
||||
cmd_view (MuStore *store, GSList *args, GError **err)
|
||||
cmd_view (MuStore *store, MuQuery *query, GSList *args, GError **err)
|
||||
{
|
||||
MuMsg *msg;
|
||||
unsigned docid;
|
||||
char *sexp;
|
||||
|
||||
return_if_fail_param_num (args, 1, 1, "view <docid>");
|
||||
return_if_fail_param_num (args, 1, 1, "view <docid>|<msgid>");
|
||||
|
||||
docid = get_docid (NULL, (const char*)args->data, err);
|
||||
docid = get_docid (query, (const char*)args->data, err);
|
||||
if (docid == MU_STORE_INVALID_DOCID)
|
||||
return server_error (err, MU_ERROR_IN_PARAMETERS,
|
||||
"invalid docid");
|
||||
|
@ -901,7 +899,7 @@ handle_command (Cmd cmd, MuStore *store, MuQuery *query, GSList *args,
|
|||
case CMD_REMOVE: rv = cmd_remove (store, args, err); break;
|
||||
case CMD_SAVE: rv = cmd_save (store, args, err); break;
|
||||
case CMD_PING: rv = cmd_ping (store, args, err); break;
|
||||
case CMD_VIEW: rv = cmd_view (store, args, err); break;
|
||||
case CMD_VIEW: rv = cmd_view (store, query, args, err); break;
|
||||
|
||||
case CMD_IGNORE: return TRUE;
|
||||
default:
|
||||
|
|
Loading…
Reference in New Issue