Commit | Line | Data |
---|---|---|
20908596 CD |
1 | ;;; org-mhe.el --- Support for links to MH-E messages from within Org-mode |
2 | ||
3 | ;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. | |
4 | ||
5 | ;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de> | |
6 | ;; Keywords: outlines, hypermedia, calendar, wp | |
7 | ;; Homepage: http://orgmode.org | |
8 | ;; Version: 6.02b | |
9 | ;; | |
10 | ;; This file is part of GNU Emacs. | |
11 | ;; | |
b1fc2b50 | 12 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
20908596 | 13 | ;; it under the terms of the GNU General Public License as published by |
b1fc2b50 GM |
14 | ;; the Free Software Foundation, either version 3 of the License, or |
15 | ;; (at your option) any later version. | |
20908596 CD |
16 | |
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. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
b1fc2b50 | 23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
20908596 CD |
24 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
25 | ;; | |
26 | ;;; Commentary: | |
27 | ||
28 | ;; This file implements links to MH-E messages from within Org-mode. | |
29 | ;; Org-mode loads this module by default - if this is not what you want, | |
30 | ;; configure the variable `org-modules'. | |
31 | ||
32 | ;;; Code: | |
33 | ||
34 | (require 'org) | |
35 | ||
36 | ;; Customization variables | |
37 | ||
38 | (defcustom org-mhe-search-all-folders nil | |
39 | "Non-nil means the search for the mh-message may extend to all folders. | |
40 | When non-nil, the search for a message will extend to all other | |
41 | folders if it cannot be found in the folder given in the link. | |
42 | Searching all folders may be slow with the default pick based | |
43 | search but is very efficient with one of the other search engines | |
44 | supported by MH-E." | |
45 | :group 'org-link-follow | |
46 | :type 'boolean) | |
47 | ||
48 | ;; Declare external functions and variables | |
49 | (declare-function mh-display-msg "mh-show" (msg-num folder-name)) | |
50 | (declare-function mh-find-path "mh-utils" ()) | |
51 | (declare-function mh-get-header-field "mh-utils" (field)) | |
52 | (declare-function mh-get-msg-num "mh-utils" (error-if-no-message)) | |
53 | (declare-function mh-header-display "mh-show" ()) | |
54 | (declare-function mh-index-previous-folder "mh-search" ()) | |
55 | (declare-function mh-normalize-folder-name "mh-utils" | |
56 | (folder &optional empty-string-okay dont-remove-trailing-slash | |
57 | return-nil-if-folder-empty)) | |
58 | (declare-function mh-search "mh-search" | |
59 | (folder search-regexp &optional redo-search-flag | |
60 | window-config)) | |
61 | (declare-function mh-search-choose "mh-search" (&optional searcher)) | |
62 | (declare-function mh-show "mh-show" (&optional message redisplay-flag)) | |
63 | (declare-function mh-show-buffer-message-number "mh-comp" (&optional buffer)) | |
64 | (declare-function mh-show-header-display "mh-show" t t) | |
65 | (declare-function mh-show-msg "mh-show" (msg)) | |
66 | (declare-function mh-show-show "mh-show" t t) | |
67 | (declare-function mh-visit-folder "mh-folder" (folder &optional | |
68 | range index-data)) | |
69 | (defvar mh-progs) | |
70 | (defvar mh-current-folder) | |
71 | (defvar mh-show-folder-buffer) | |
72 | (defvar mh-index-folder) | |
73 | (defvar mh-searcher) | |
74 | ||
75 | ;; Install the link type | |
76 | (org-add-link-type "mhe" 'org-mhe-open) | |
77 | (add-hook 'org-store-link-functions 'org-mhe-store-link) | |
78 | ||
79 | ;; Implementation | |
80 | (defun org-mhe-store-link () | |
81 | "Store a link to an MH-E folder or message." | |
82 | (when (or (equal major-mode 'mh-folder-mode) | |
83 | (equal major-mode 'mh-show-mode)) | |
84 | (let ((from (org-mhe-get-header "From:")) | |
85 | (to (org-mhe-get-header "To:")) | |
86 | (message-id (org-mhe-get-header "Message-Id:")) | |
87 | (subject (org-mhe-get-header "Subject:")) | |
88 | link desc) | |
89 | (org-store-link-props :type "mh" :from from :to to | |
90 | :subject subject :message-id message-id) | |
91 | (setq desc (org-email-link-description)) | |
92 | (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#" | |
93 | (org-remove-angle-brackets message-id))) | |
94 | (org-add-link-props :link link :description desc) | |
95 | link))) | |
96 | ||
97 | (defun org-mhe-open (path) | |
98 | "Follow an MH-E message link specified by PATH." | |
99 | (let (folder article) | |
100 | (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) | |
101 | (error "Error in MH-E link")) | |
102 | (setq folder (match-string 1 path) | |
103 | article (match-string 3 path)) | |
104 | (org-mhe-follow-link folder article))) | |
105 | ||
106 | ;;; mh-e integration based on planner-mode | |
107 | (defun org-mhe-get-message-real-folder () | |
108 | "Return the name of the real folder for the current message. | |
109 | So if you use sequences, it will now work." | |
110 | (save-excursion | |
111 | (let* ((folder | |
112 | (if (equal major-mode 'mh-folder-mode) | |
113 | mh-current-folder | |
114 | ;; Refer to the show buffer | |
115 | mh-show-folder-buffer)) | |
116 | (end-index | |
117 | (if (boundp 'mh-index-folder) | |
118 | (min (length mh-index-folder) (length folder)))) | |
119 | ) | |
120 | ;; a simple test on mh-index-data does not work, because | |
121 | ;; mh-index-data is always nil in a show buffer. | |
122 | (if (and (boundp 'mh-index-folder) | |
123 | (string= mh-index-folder (substring folder 0 end-index))) | |
124 | (if (equal major-mode 'mh-show-mode) | |
125 | (save-window-excursion | |
126 | (let (pop-up-frames) | |
127 | (when (buffer-live-p (get-buffer folder)) | |
128 | (progn | |
129 | (pop-to-buffer folder) | |
130 | (org-mhe-get-message-folder-from-index) | |
131 | ) | |
132 | ))) | |
133 | (org-mhe-get-message-folder-from-index) | |
134 | ) | |
135 | folder | |
136 | ) | |
137 | ))) | |
138 | ||
139 | (defun org-mhe-get-message-folder-from-index () | |
140 | "Return the name of the message folder in a index folder buffer." | |
141 | (save-excursion | |
142 | (mh-index-previous-folder) | |
143 | (re-search-forward "^\\(+.*\\)$" nil t) | |
144 | (message "%s" (match-string 1)))) | |
145 | ||
146 | (defun org-mhe-get-message-folder () | |
147 | "Return the name of the current message folder. | |
148 | Be careful if you use sequences." | |
149 | (save-excursion | |
150 | (if (equal major-mode 'mh-folder-mode) | |
151 | mh-current-folder | |
152 | ;; Refer to the show buffer | |
153 | mh-show-folder-buffer))) | |
154 | ||
155 | (defun org-mhe-get-message-num () | |
156 | "Return the number of the current message. | |
157 | Be careful if you use sequences." | |
158 | (save-excursion | |
159 | (if (equal major-mode 'mh-folder-mode) | |
160 | (mh-get-msg-num nil) | |
161 | ;; Refer to the show buffer | |
162 | (mh-show-buffer-message-number)))) | |
163 | ||
164 | (defun org-mhe-get-header (header) | |
165 | "Return the field for HEADER of the message in folder mode. | |
166 | This will create a show buffer for the corresponding message. If | |
167 | you have a better idea of how to do this then please let us know." | |
168 | (let* ((folder (org-mhe-get-message-folder)) | |
169 | (num (org-mhe-get-message-num)) | |
170 | (buffer (get-buffer-create (concat "show-" folder))) | |
171 | (header-field)) | |
172 | (with-current-buffer buffer | |
173 | (mh-display-msg num folder) | |
174 | (if (equal major-mode 'mh-folder-mode) | |
175 | (mh-header-display) | |
176 | (mh-show-header-display)) | |
177 | (set-buffer buffer) | |
178 | (setq header-field (mh-get-header-field header)) | |
179 | (if (equal major-mode 'mh-folder-mode) | |
180 | (mh-show) | |
181 | (mh-show-show)) | |
182 | header-field))) | |
183 | ||
184 | (defun org-mhe-follow-link (folder article) | |
185 | "Follow an MH-E link to FOLDER and ARTICLE. | |
186 | If ARTICLE is nil FOLDER is shown. If the configuration variable | |
187 | `org-mhe-search-all-folders' is t and `mh-searcher' is pick, | |
188 | ARTICLE is searched in all folders. Indexed searches (swish++, | |
189 | namazu, and others supported by MH-E) will always search in all | |
190 | folders." | |
191 | (require 'mh-e) | |
192 | (require 'mh-search) | |
193 | (require 'mh-utils) | |
194 | (mh-find-path) | |
195 | (if (not article) | |
196 | (mh-visit-folder (mh-normalize-folder-name folder)) | |
197 | (setq article (org-add-angle-brackets article)) | |
198 | (mh-search-choose) | |
199 | (if (equal mh-searcher 'pick) | |
200 | (progn | |
201 | (mh-search folder (list "--message-id" article)) | |
202 | (when (and org-mhe-search-all-folders | |
203 | (not (org-mhe-get-message-real-folder))) | |
204 | (kill-this-buffer) | |
205 | (mh-search "+" (list "--message-id" article)))) | |
206 | (mh-search "+" article)) | |
207 | (if (org-mhe-get-message-real-folder) | |
208 | (mh-show-msg 1) | |
209 | (kill-this-buffer) | |
210 | (error "Message not found")))) | |
211 | ||
212 | (provide 'org-mhe) | |
213 | ||
88ac7b50 | 214 | ;; arch-tag: dcb05484-8627-491d-a8c1-01dbd2bde4ae |
20908596 | 215 | ;;; org-mhe.el ends here |