1 ;;; org-mhe.el - Support for links to MHE messages in Org-mode
3 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 ;; Author: Carsten Dominik <carsten at orgmode dot org>
6 ;; Keywords: outlines, hypermedia, calendar, wp
7 ;; Homepage: http://orgmode.org
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
30 ;; This file implements links to MHE messages for Org-mode.
31 ;; Org-mode loads this module by default - if this is not what you want,
32 ;; configure the variable `org-modules'.
36 ;; Customization variables
37 (defcustom org-mhe-search-all-folders nil
38 "Non-nil means, that the search for the mh-message will be extended to
39 all folders if the message cannot be found in the folder given in the link.
40 Searching all folders is very efficient with one of the search engines
41 supported by MH-E, but will be slow with pick."
42 :group
'org-link-follow
45 ;; Declare external functions and variables
46 (declare-function mh-display-msg
"mh-show" (msg-num folder-name
))
47 (declare-function mh-find-path
"mh-utils" ())
48 (declare-function mh-get-header-field
"mh-utils" (field))
49 (declare-function mh-get-msg-num
"mh-utils" (error-if-no-message))
50 (declare-function mh-header-display
"mh-show" ())
51 (declare-function mh-index-previous-folder
"mh-search" ())
52 (declare-function mh-normalize-folder-name
"mh-utils"
53 (folder &optional empty-string-okay dont-remove-trailing-slash
54 return-nil-if-folder-empty
))
55 (declare-function mh-search
"mh-search"
56 (folder search-regexp
&optional redo-search-flag
58 (declare-function mh-search-choose
"mh-search" (&optional searcher
))
59 (declare-function mh-show
"mh-show" (&optional message redisplay-flag
))
60 (declare-function mh-show-buffer-message-number
"mh-comp" (&optional buffer
))
61 (declare-function mh-show-header-display
"mh-show" t t
)
62 (declare-function mh-show-msg
"mh-show" (msg))
63 (declare-function mh-show-show
"mh-show" t t
)
64 (declare-function mh-visit-folder
"mh-folder" (folder &optional
67 (defvar mh-current-folder
)
68 (defvar mh-show-folder-buffer
)
69 (defvar mh-index-folder
)
72 ;; Install the link type
73 (org-add-link-type "mhe" 'org-mhe-open
)
74 (add-hook 'org-store-link-functions
'org-mhe-store-link
)
77 (defun org-mhe-store-link ()
78 "Store a link to an MHE folder or message."
79 (when (or (equal major-mode
'mh-folder-mode
)
80 (equal major-mode
'mh-show-mode
))
81 (let ((from (org-mhe-get-header "From:"))
82 (to (org-mhe-get-header "To:"))
83 (message-id (org-mhe-get-header "Message-Id:"))
84 (subject (org-mhe-get-header "Subject:"))
86 (org-store-link-props :type
"mh" :from from
:to to
87 :subject subject
:message-id message-id
)
88 (setq desc
(org-email-link-description))
89 (setq link
(org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
90 (org-remove-angle-brackets message-id
)))
91 (org-add-link-props :link link
:description desc
)
94 (defun org-mhe-open (path)
95 "Follow an MHE message link."
97 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path
))
98 (error "Error in MHE link"))
99 (setq folder
(match-string 1 path
)
100 article
(match-string 3 path
))
101 (org-mhe-follow-link folder article
)))
103 ;;; mh-e integration based on planner-mode
104 (defun org-mhe-get-message-real-folder ()
105 "Return the name of the current message real folder, so if you use
106 sequences, it will now work."
109 (if (equal major-mode
'mh-folder-mode
)
111 ;; Refer to the show buffer
112 mh-show-folder-buffer
))
114 (if (boundp 'mh-index-folder
)
115 (min (length mh-index-folder
) (length folder
))))
117 ;; a simple test on mh-index-data does not work, because
118 ;; mh-index-data is always nil in a show buffer.
119 (if (and (boundp 'mh-index-folder
)
120 (string= mh-index-folder
(substring folder
0 end-index
)))
121 (if (equal major-mode
'mh-show-mode
)
122 (save-window-excursion
124 (when (buffer-live-p (get-buffer folder
))
126 (pop-to-buffer folder
)
127 (org-mhe-get-message-folder-from-index)
130 (org-mhe-get-message-folder-from-index)
136 (defun org-mhe-get-message-folder-from-index ()
137 "Returns the name of the message folder in a index folder buffer."
139 (mh-index-previous-folder)
140 (re-search-forward "^\\(+.*\\)$" nil t
)
141 (message "%s" (match-string 1))))
143 (defun org-mhe-get-message-folder ()
144 "Return the name of the current message folder. Be careful if you
147 (if (equal major-mode
'mh-folder-mode
)
149 ;; Refer to the show buffer
150 mh-show-folder-buffer
)))
152 (defun org-mhe-get-message-num ()
153 "Return the number of the current message. Be careful if you
156 (if (equal major-mode
'mh-folder-mode
)
158 ;; Refer to the show buffer
159 (mh-show-buffer-message-number))))
161 (defun org-mhe-get-header (header)
162 "Return a header of the message in folder mode. This will create a
163 show buffer for the corresponding message. If you have a more clever
165 (let* ((folder (org-mhe-get-message-folder))
166 (num (org-mhe-get-message-num))
167 (buffer (get-buffer-create (concat "show-" folder
)))
169 (with-current-buffer buffer
170 (mh-display-msg num folder
)
171 (if (equal major-mode
'mh-folder-mode
)
173 (mh-show-header-display))
175 (setq header-field
(mh-get-header-field header
))
176 (if (equal major-mode
'mh-folder-mode
)
181 (defun org-mhe-follow-link (folder article
)
182 "Follow an MHE link to FOLDER and ARTICLE.
183 If ARTICLE is nil FOLDER is shown. If the configuration variable
184 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
185 ARTICLE is searched in all folders. Indexed searches (swish++,
186 namazu, and others supported by MH-E) will always search in all
193 (mh-visit-folder (mh-normalize-folder-name folder
))
194 (setq article
(org-add-angle-brackets article
))
196 (if (equal mh-searcher
'pick
)
198 (mh-search folder
(list "--message-id" article
))
199 (when (and org-mhe-search-all-folders
200 (not (org-mhe-get-message-real-folder)))
202 (mh-search "+" (list "--message-id" article
))))
203 (mh-search "+" article
))
204 (if (org-mhe-get-message-real-folder)
207 (error "Message not found"))))
211 ;;; org-mhe.el ends here