Browse Source

Update org-mairix.el to version 0.5.

Carsten Dominik 16 years ago
parent
commit
19b5215b81
3 changed files with 191 additions and 82 deletions
  1. 4 0
      contrib/ChangeLog
  2. 182 82
      contrib/lisp/org-mairix.el
  3. 5 0
      lisp/ChangeLog

+ 4 - 0
contrib/ChangeLog

@@ -1,3 +1,7 @@
+2008-09-02  Carsten Dominik  <dominik@science.uva.nl>
+
+	* lisp/org-mairix.el: Update to version 0.5.
+
 2008-07-04  Christian Egli  <christian.egli@alumni.ethz.ch>
 2008-07-04  Christian Egli  <christian.egli@alumni.ethz.ch>
 
 
 	* scripts/org2hpda: the default location of the diary file should
 	* scripts/org2hpda: the default location of the diary file should

+ 182 - 82
contrib/lisp/org-mairix.el

@@ -1,12 +1,13 @@
 ;;; org-mairix.el - Support for hooking mairix search into Org for different MUAs
 ;;; org-mairix.el - Support for hooking mairix search into Org for different MUAs
 ;;
 ;;
 ;; Copyright (C) 2007 Georg C. F. Greve
 ;; Copyright (C) 2007 Georg C. F. Greve
+;; mutt support by Adam Spiers <orgmode at adamspiers dot org>
 ;;
 ;;
 ;; Author: Georg C. F. Greve <greve at fsfeurope dot org>
 ;; Author: Georg C. F. Greve <greve at fsfeurope dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp, email, mairix
 ;; Keywords: outlines, hypermedia, calendar, wp, email, mairix
 ;; Purpose: Integrate mairix email searching into Org mode
 ;; Purpose: Integrate mairix email searching into Org mode
 ;; See http://orgmode.org and http://www.rpcurnow.force9.co.uk/mairix/
 ;; See http://orgmode.org and http://www.rpcurnow.force9.co.uk/mairix/
-;; Version: 0.4
+;; Version: 0.5
 ;;
 ;;
 ;; This file is Free Software; you can redistribute it and/or modify
 ;; This file is Free Software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; it under the terms of the GNU General Public License as published by
@@ -27,8 +28,8 @@
 ;;
 ;;
 ;; You will need to configure mairix first, which involves setting up your
 ;; You will need to configure mairix first, which involves setting up your
 ;; .mairixrc in your home directory. Once it is working, you should set up
 ;; .mairixrc in your home directory. Once it is working, you should set up
-;; your way to display results in your favorite way -- usually a MUA, in my
-;; case gnus.
+;; your way to display results in your favorite way -- usually a MUA.
+;; Currently gnus and mutt are supported.
 ;;
 ;;
 ;; After both steps are done, all you should need to hook mairix, org
 ;; After both steps are done, all you should need to hook mairix, org
 ;; and your MUA together is to do (require 'org-mairix) in your
 ;; and your MUA together is to do (require 'org-mairix) in your
@@ -44,7 +45,7 @@
 (defgroup org-mairix nil
 (defgroup org-mairix nil
   "Mairix support/integration in org."
   "Mairix support/integration in org."
   :tag "Org Mairix"
   :tag "Org Mairix"
-  :group 'org-links)
+  :group 'org)
 
 
 (defcustom org-mairix-threaded-links t
 (defcustom org-mairix-threaded-links t
   "Should new links be created as threaded links?
   "Should new links be created as threaded links?
@@ -70,67 +71,58 @@ Defaults to Gnus, feel free to add your own MUAs or methods."
   :group 'org-mairix
   :group 'org-mairix
   :type 'hook)
   :type 'hook)
 
 
-(defcustom org-mairix-executable "mairix"
-  "The mairix executable to call. If your paths are set up
-correctly, you should not need to change this."
-  :group 'org-mairix
-  :type 'string)
+(defcustom org-mairix-open-command "mairix %args% '%search%'"
+  "The mairix command-line to use. If your paths are set up
+correctly, you should not need to change this.
 
 
-(defgroup org-mairix-gnus nil
-  "Use gnus for mairix support in org."
-  :tag "Org Mairix Gnus"
-  :group 'org-mairix)
-
-(defcustom org-mairix-gnus-results-group "nnmaildir:mairix"
-  "The group that is configured to hold the mairix search results,
-which needs to be setup independently of the org-mairix integration,
-along with general mairix configuration."
-  :group 'org-mairix-gnus
+'%search%' will get substituted with the search expression, and
+'%args%' with any additional arguments."
+  :group 'org-mairix
   :type 'string)
   :type 'string)
 
 
-(defcustom org-mairix-gnus-select-display-group-function 'org-mairix-gnus-select-display-group-function-gg
-  "Hook to call to select the group that contains the matching articles.
-We should not need this, it is owed to a problem of gnus that people were
-not yet able to figure out, see
- http://article.gmane.org/gmane.emacs.gnus.general/65248
- http://article.gmane.org/gmane.emacs.gnus.general/65265
- http://article.gmane.org/gmane.emacs.gnus.user/9596
-for reference.
-
-It seems gnus needs a 'forget/ignore everything you think you
-know about that group' function. Volunteers?"
-  :group 'org-mairix-gnus
-  :type 'hook)
-
-
 ;;; The hooks to integrate mairix into org
 ;;; The hooks to integrate mairix into org
 
 
 (org-add-link-type "mairix" 'org-mairix-open)
 (org-add-link-type "mairix" 'org-mairix-open)
-(add-hook 'org-store-link-functions 'org-mairix-store-link)
-
+(add-hook 'org-store-link-functions 'org-mairix-store-gnus-link)
 
 
 ;;; Generic org-mairix functions
 ;;; Generic org-mairix functions
 
 
-(defun org-mairix-store-link ()
-  "Store a link to the current message as a Mairix search for its
-Message ID."
-
-  ;; gnus integration
-  (when (memq major-mode '(gnus-summary-mode gnus-article-mode))
-    (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
-    (let* ((article (gnus-summary-article-number))
-	   (header (gnus-summary-article-header article))
-	   (from (mail-header-from header))
-	   (message-id (mail-header-id header))
-	   (subject (gnus-summary-subject-string)))
-      (org-store-link-props :type "mairix" :from from :subject subject
-			    :message-id message-id)
-      (setq cpltxt (org-email-link-description))
-      (org-store-link-props :link (concat "mairix:"
-					  (if org-mairix-threaded-links "t:")
-					  (if org-mairix-augmented-links "a:")
-					  "@@" (org-remove-angle-brackets message-id))
-			    :description cpltxt))))
+(defun org-mairix-construct-link (message-id)
+  "Construct a mairix: hyperlink based on message-id."
+  (concat "mairix:"
+          (if org-mairix-threaded-links "t:")
+          (if org-mairix-augmented-links "a:")
+          "@@"
+          (org-remove-angle-brackets message-id)))
+
+(defun org-store-mairix-link-props (&rest plist)
+  "Take a property list describing a mail, and add mairix link
+and description properties so that org can build a mairix link to
+it."
+  ;; We have to call `org-store-link-props' twice:
+  ;;
+  ;;   - It extracts 'fromname'/'fromaddress' from 'from' property,
+  ;;     and stores the updated plist to `org-store-link-plist'.
+  ;;
+  ;;   - `org-email-link-description' uses these new properties to
+  ;;     build a description from the previously stored plist.  I
+  ;;     wrote a tiny patch to `org-email-link-description' so it
+  ;;     could take a non-stored plist as an optional 2nd argument,
+  ;;     but the plist provided still needs 'fromname'/'fromaddress'.
+  ;;
+  ;;   - Ideally we would decouple the storing bit of
+  ;;     `org-store-link-props' from the extraction bit, but lots of
+  ;;     stuff in `org-store-link' which calls it would need to be
+  ;;     changed.  Maybe just factor out the extraction so it can be
+  ;;     reused separately?
+  (let ((mid (plist-get plist :message-id)))
+    (apply 'org-store-link-props
+           (append plist
+                   (list :type "mairix"
+                         :link (org-mairix-construct-link mid))))
+    (apply 'org-store-link-props
+           (append org-store-link-plist
+                   (list :description (org-email-link-description))))))
 
 
 (defun org-mairix-message-send-and-exit-with-link ()
 (defun org-mairix-message-send-and-exit-with-link ()
   "Function that can be assigned as an alternative sending function,
   "Function that can be assigned as an alternative sending function,
@@ -139,47 +131,151 @@ the buffer just like 'message-send-and-exit' does."
   (interactive)
   (interactive)
   (message-send)
   (message-send)
   (let* ((message-id (message-fetch-field "Message-Id"))
   (let* ((message-id (message-fetch-field "Message-Id"))
-	 (subject (message-fetch-field "Subject"))
-	 (link (concat "mairix:"
-		       (if org-mairix-threaded-links "t:")
-		       (if org-mairix-augmented-links "a:")
-		       "@@" (org-remove-angle-brackets message-id)))
-	 (desc (concat "Email: '" subject "'")))
+         (subject (message-fetch-field "Subject"))
+         (link (org-mairix-construct-link message-id))
+         (desc (concat "Email: '" subject "'")))
     (setq org-stored-links
     (setq org-stored-links
-	  (cons (list link desc) org-stored-links)))
+          (cons (list link desc) org-stored-links)))
   (message-bury (current-buffer)))
   (message-bury (current-buffer)))
 
 
-(defun org-mairix-open (path)
+(defun org-mairix-open (search)
   "Function to open mairix link.
   "Function to open mairix link.
 
 
 We first need to split it into its individual parts, and then
 We first need to split it into its individual parts, and then
 extract the message-id to be passed on to the display function
 extract the message-id to be passed on to the display function
 before call mairix, evaluate the number of matches returned, and
 before call mairix, evaluate the number of matches returned, and
 make sure to only call display of mairix succeeded in matching."
 make sure to only call display of mairix succeeded in matching."
-  (let* ((cmdline org-mairix-executable))
-    (if (string< "t:" path)
-	(progn (setq path (substring path 2 nil))
-	       (setq cmdline (concat cmdline " --threads"))))
-    (if (string< "a:" path)
-	(progn (setq path (substring path 2 nil))
-	       (setq cmdline (concat cmdline " --augment"))))
-    (let* ((message-id (substring path 2 nil)))
-      (setq cmdline (concat cmdline " m:" message-id))
-
+  (let* ((args ""))
+    (if (equal (substring search 0 2) "t:" )
+        (progn (setq search (substring search 2 nil))
+               (setq args (concat args " --threads"))))
+    (if (equal (substring search 0 2) "a:")
+        (progn (setq search (substring search 2 nil))
+               (setq args (concat args " --augment"))))
+    (let ((cmdline (org-mairix-command-substitution
+                    org-mairix-open-command search args)))
       (print cmdline)
       (print cmdline)
-
-      (setq retval (shell-command-to-string
-		    (concat cmdline " m:" message-id)))
+      (setq retval (shell-command-to-string cmdline))
       (string-match "\[0-9\]+" retval)
       (string-match "\[0-9\]+" retval)
       (setq matches (string-to-number (match-string 0 retval)))
       (setq matches (string-to-number (match-string 0 retval)))
       (if (eq matches 0) (message "Link failed: no matches, sorry")
       (if (eq matches 0) (message "Link failed: no matches, sorry")
-	(message "Link returned %d matches" matches)
-	(run-hook-with-args 'org-mairix-display-hook message-id)))))
+        (message "Link returned %d matches" matches)
+        (run-hook-with-args 'org-mairix-display-hook search args)))))
+
+(defun org-mairix-command-substitution (cmd search args)
+  "Substitute '%search%' and '%args% in mairix search command."
+  (while (string-match "%search%" cmd)
+    (setq cmd (replace-match search 'fixedcase 'literal cmd)))
+  (while (string-match "%args%" cmd)
+    (setq cmd (replace-match args 'fixedcase 'literal cmd)))
+  cmd)
+
+;;; Functions necessary for integration of external MUAs.
+
+;; Of course we cannot call `org-store-link' from within an external
+;; MUA, so we need some other way of storing a link for later
+;; retrieval by org-mode and/or remember-mode.  To do this we use a
+;; temporary file as a kind of dedicated clipboard.
+
+(defcustom org-mairix-link-clipboard "~/.org-mairix-link"
+  "Pseudo-clipboard file where mairix URLs get copied to by external
+applications in order to mimic `org-store-link'.  Used by
+`org-mairix-insert-link'."
+  :group 'org-mairix
+  :type 'string)
 
 
+;; When we resolve some of the issues with `org-store-link' detailed
+;; at <http://thread.gmane.org/gmane.emacs.orgmode/4217/focus=4635>,
+;; we might not need org-mairix-insert-link.
+
+(defun org-mairix-insert-link ()
+  "Insert link from file defined by `org-mairix-link-clipboard'."
+  (interactive)
+  (let ((bytes (cadr (insert-file-contents
+                      (expand-file-name org-mairix-link-clipboard)))))
+    (forward-char bytes)
+    (save-excursion
+      (forward-char -1)
+      (if (looking-at "\n")
+          (delete-char 1)))))
+
+;;; Functions necessary for mutt integration
+
+(defgroup org-mairix-mutt nil
+  "Use mutt for mairix support in org."
+  :tag "Org Mairix Mutt"
+  :group 'org-mairix)
+
+(defcustom org-mairix-mutt-display-command
+  "xterm -title 'mairix search: %search%' -e 'unset COLUMNS; mutt -f 
+~/mail/mairix -e \"push <display-message>\"' &"
+  "Command to execute to display mairix search results via mutt within
+an xterm.
+
+'%search%' will get substituted with the search expression, and
+'%args%' with any additional arguments used in the search."
+  :group 'org-mairix-mutt
+  :type 'string)
+
+(defun org-mairix-mutt-display-results (search args)
+  "Display results of mairix search in mutt, using the command line
+defined in `org-mairix-mutt-display-command'."
+  ;; By default, async `shell-command' invocations display the temp
+  ;; buffer, which is annoying here.  We choose a deterministic
+  ;; buffer name so we can hide it again immediately.
+  ;; Note: `call-process' is synchronous so not useful here.
+  (let ((cmd (org-mairix-command-substitution
+              org-mairix-mutt-display-command search args))
+        (tmpbufname (generate-new-buffer-name " *mairix-view*")))
+    (shell-command cmd tmpbufname)
+    (delete-windows-on (get-buffer tmpbufname))))
 
 
 ;;; Functions necessary for gnus integration
 ;;; Functions necessary for gnus integration
 
 
-(defun org-mairix-gnus-display-results (message-id)
+(defgroup org-mairix-gnus nil
+  "Use gnus for mairix support in org."
+  :tag "Org Mairix Gnus"
+  :group 'org-mairix)
+
+(defcustom org-mairix-gnus-results-group "nnmaildir:mairix"
+  "The group that is configured to hold the mairix search results,
+which needs to be setup independently of the org-mairix integration,
+along with general mairix configuration."
+  :group 'org-mairix-gnus
+  :type 'string)
+
+(defcustom org-mairix-gnus-select-display-group-function 
+'org-mairix-gnus-select-display-group-function-gg
+  "Hook to call to select the group that contains the matching articles.
+We should not need this, it is owed to a problem of gnus that people were
+not yet able to figure out, see
+ http://article.gmane.org/gmane.emacs.gnus.general/65248
+ http://article.gmane.org/gmane.emacs.gnus.general/65265
+ http://article.gmane.org/gmane.emacs.gnus.user/9596
+for reference.
+
+It seems gnus needs a 'forget/ignore everything you think you
+know about that group' function. Volunteers?"
+  :group 'org-mairix-gnus
+  :type 'hook)
+
+(defun org-mairix-store-gnus-link ()
+  "Store a link to the current gnus message as a Mairix search for its
+Message ID."
+
+  ;; gnus integration
+  (when (memq major-mode '(gnus-summary-mode gnus-article-mode))
+    (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
+    (let* ((article (gnus-summary-article-number))
+           (header (gnus-summary-article-header article))
+           (from (mail-header-from header))
+           (message-id (mail-header-id header))
+           (subject (gnus-summary-subject-string)))
+      (org-store-mairix-link-props :from from
+                                   :subject subject
+                                   :message-id message-id))))
+
+(defun org-mairix-gnus-display-results (search args)
   "Display results of mairix search in Gnus.
   "Display results of mairix search in Gnus.
 
 
 Note: This does not work as cleanly as I would like it to. The
 Note: This does not work as cleanly as I would like it to. The
@@ -188,6 +284,10 @@ without remembering anything. At the moment it seems to be unable
 to do that -- so you're likely to see zombies floating around.
 to do that -- so you're likely to see zombies floating around.
 
 
 If you can improve this, please do!"
 If you can improve this, please do!"
+  (if (not (equal (substring search 0 2) "m:" ))
+      (error "org-mairix-gnus-display-results: display of search other than 
+message-id not implemented yet"))
+  (setq message-id (substring search 2 nil))
   (require 'gnus)
   (require 'gnus)
   (require 'gnus-sum)
   (require 'gnus-sum)
   ;; FIXME: (bzg/gg) We might need to make sure gnus is running here,
   ;; FIXME: (bzg/gg) We might need to make sure gnus is running here,
@@ -213,8 +313,6 @@ If you can improve this, please do!"
   (gnus-summary-select-article
   (gnus-summary-select-article
    nil t t (car (gnus-find-matching-articles "message-id" message-id))))
    nil t t (car (gnus-find-matching-articles "message-id" message-id))))
 
 
-(provide 'org-mairix)
-
 (defun org-mairix-gnus-select-display-group-function-gg ()
 (defun org-mairix-gnus-select-display-group-function-gg ()
   "Georg's hack to select a group that gnus (falsely) believes to be
   "Georg's hack to select a group that gnus (falsely) believes to be
 empty to then call rebuilding of the summary. It leaves zombies of
 empty to then call rebuilding of the summary. It leaves zombies of
@@ -229,4 +327,6 @@ using better for Bastien, so it may work for you."
   (gnus-group-clear-data org-mairix-gnus-results-group)
   (gnus-group-clear-data org-mairix-gnus-results-group)
   (gnus-group-read-group t nil org-mairix-gnus-results-group))
   (gnus-group-read-group t nil org-mairix-gnus-results-group))
 
 
+(provide 'org-mairix)
+
 ;;; org-mairix.el ends here
 ;;; org-mairix.el ends here

+ 5 - 0
lisp/ChangeLog

@@ -1,3 +1,8 @@
+2008-09-01  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org-exp.el (org-html-do-expand): Allow {} to terminate
+	tex macro
+
 2008-07-29  Carsten Dominik  <dominik@science.uva.nl>
 2008-07-29  Carsten Dominik  <dominik@science.uva.nl>
 
 
 	* org.el (org-buffer-list): Select buffers based on major mode,
 	* org.el (org-buffer-list): Select buffers based on major mode,