Commit | Line | Data |
---|---|---|
20908596 CD |
1 | ;;; org-mhe.el --- Support for links to MH-E messages from within Org-mode |
2 | ||
ba318903 | 3 | ;; Copyright (C) 2004-2014 Free Software Foundation, Inc. |
20908596 CD |
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 | |
20908596 CD |
8 | ;; |
9 | ;; This file is part of GNU Emacs. | |
10 | ;; | |
b1fc2b50 | 11 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
20908596 | 12 | ;; it under the terms of the GNU General Public License as published by |
b1fc2b50 GM |
13 | ;; the Free Software Foundation, either version 3 of the License, or |
14 | ;; (at your option) any later version. | |
20908596 CD |
15 | |
16 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | ;; GNU General Public License for more details. | |
20 | ||
21 | ;; You should have received a copy of the GNU General Public License | |
b1fc2b50 | 22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
20908596 CD |
23 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
24 | ;; | |
25 | ;;; Commentary: | |
26 | ||
27 | ;; This file implements links to MH-E messages from within Org-mode. | |
28 | ;; Org-mode loads this module by default - if this is not what you want, | |
29 | ;; configure the variable `org-modules'. | |
30 | ||
31 | ;;; Code: | |
32 | ||
271672fa | 33 | (require 'org-macs) |
20908596 CD |
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) | |
b349f79f | 74 | (defvar mh-search-regexp-builder) |
20908596 CD |
75 | |
76 | ;; Install the link type | |
77 | (org-add-link-type "mhe" 'org-mhe-open) | |
78 | (add-hook 'org-store-link-functions 'org-mhe-store-link) | |
79 | ||
80 | ;; Implementation | |
81 | (defun org-mhe-store-link () | |
82 | "Store a link to an MH-E folder or message." | |
83 | (when (or (equal major-mode 'mh-folder-mode) | |
84 | (equal major-mode 'mh-show-mode)) | |
3ab2c837 BG |
85 | (save-window-excursion |
86 | (let* ((from (org-mhe-get-header "From:")) | |
87 | (to (org-mhe-get-header "To:")) | |
88 | (message-id (org-mhe-get-header "Message-Id:")) | |
89 | (subject (org-mhe-get-header "Subject:")) | |
90 | (date (org-mhe-get-header "Date:")) | |
91 | (date-ts (and date (format-time-string | |
92 | (org-time-stamp-format t) (date-to-time date)))) | |
93 | (date-ts-ia (and date (format-time-string | |
94 | (org-time-stamp-format t t) | |
95 | (date-to-time date)))) | |
96 | link desc) | |
97 | (org-store-link-props :type "mh" :from from :to to | |
98 | :subject subject :message-id message-id) | |
99 | (when date | |
100 | (org-add-link-props :date date :date-timestamp date-ts | |
101 | :date-timestamp-inactive date-ts-ia)) | |
102 | (setq desc (org-email-link-description)) | |
8223b1d2 BG |
103 | (setq link (concat "mhe:" (org-mhe-get-message-real-folder) "#" |
104 | (org-remove-angle-brackets message-id))) | |
3ab2c837 BG |
105 | (org-add-link-props :link link :description desc) |
106 | link)))) | |
20908596 CD |
107 | |
108 | (defun org-mhe-open (path) | |
109 | "Follow an MH-E message link specified by PATH." | |
110 | (let (folder article) | |
111 | (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path)) | |
112 | (error "Error in MH-E link")) | |
113 | (setq folder (match-string 1 path) | |
114 | article (match-string 3 path)) | |
115 | (org-mhe-follow-link folder article))) | |
116 | ||
117 | ;;; mh-e integration based on planner-mode | |
118 | (defun org-mhe-get-message-real-folder () | |
119 | "Return the name of the real folder for the current message. | |
120 | So if you use sequences, it will now work." | |
121 | (save-excursion | |
122 | (let* ((folder | |
33306645 CD |
123 | (if (equal major-mode 'mh-folder-mode) |
124 | mh-current-folder | |
125 | ;; Refer to the show buffer | |
126 | mh-show-folder-buffer)) | |
127 | (end-index | |
128 | (if (boundp 'mh-index-folder) | |
129 | (min (length mh-index-folder) (length folder)))) | |
130 | ) | |
20908596 CD |
131 | ;; a simple test on mh-index-data does not work, because |
132 | ;; mh-index-data is always nil in a show buffer. | |
133 | (if (and (boundp 'mh-index-folder) | |
33306645 CD |
134 | (string= mh-index-folder (substring folder 0 end-index))) |
135 | (if (equal major-mode 'mh-show-mode) | |
136 | (save-window-excursion | |
20908596 CD |
137 | (let (pop-up-frames) |
138 | (when (buffer-live-p (get-buffer folder)) | |
139 | (progn | |
140 | (pop-to-buffer folder) | |
141 | (org-mhe-get-message-folder-from-index) | |
142 | ) | |
143 | ))) | |
33306645 CD |
144 | (org-mhe-get-message-folder-from-index) |
145 | ) | |
146 | folder | |
147 | ) | |
20908596 CD |
148 | ))) |
149 | ||
150 | (defun org-mhe-get-message-folder-from-index () | |
b349f79f | 151 | "Return the name of the message folder in an index folder buffer." |
20908596 CD |
152 | (save-excursion |
153 | (mh-index-previous-folder) | |
b349f79f CD |
154 | (if (re-search-forward "^\\(+.*\\)$" nil t) |
155 | (message "%s" (match-string 1))))) | |
20908596 CD |
156 | |
157 | (defun org-mhe-get-message-folder () | |
158 | "Return the name of the current message folder. | |
159 | Be careful if you use sequences." | |
160 | (save-excursion | |
161 | (if (equal major-mode 'mh-folder-mode) | |
33306645 | 162 | mh-current-folder |
20908596 CD |
163 | ;; Refer to the show buffer |
164 | mh-show-folder-buffer))) | |
165 | ||
166 | (defun org-mhe-get-message-num () | |
167 | "Return the number of the current message. | |
168 | Be careful if you use sequences." | |
169 | (save-excursion | |
170 | (if (equal major-mode 'mh-folder-mode) | |
33306645 | 171 | (mh-get-msg-num nil) |
20908596 CD |
172 | ;; Refer to the show buffer |
173 | (mh-show-buffer-message-number)))) | |
174 | ||
175 | (defun org-mhe-get-header (header) | |
176 | "Return the field for HEADER of the message in folder mode. | |
177 | This will create a show buffer for the corresponding message. If | |
178 | you have a better idea of how to do this then please let us know." | |
179 | (let* ((folder (org-mhe-get-message-folder)) | |
33306645 CD |
180 | (num (org-mhe-get-message-num)) |
181 | (buffer (get-buffer-create (concat "show-" folder))) | |
182 | (header-field)) | |
8223b1d2 BG |
183 | (with-current-buffer buffer |
184 | (mh-display-msg num folder) | |
185 | (if (equal major-mode 'mh-folder-mode) | |
186 | (mh-header-display) | |
187 | (mh-show-header-display)) | |
188 | (set-buffer buffer) | |
189 | (setq header-field (mh-get-header-field header)) | |
190 | (if (equal major-mode 'mh-folder-mode) | |
191 | (mh-show) | |
192 | (mh-show-show)) | |
193 | (org-trim header-field)))) | |
20908596 CD |
194 | |
195 | (defun org-mhe-follow-link (folder article) | |
196 | "Follow an MH-E link to FOLDER and ARTICLE. | |
197 | If ARTICLE is nil FOLDER is shown. If the configuration variable | |
198 | `org-mhe-search-all-folders' is t and `mh-searcher' is pick, | |
199 | ARTICLE is searched in all folders. Indexed searches (swish++, | |
200 | namazu, and others supported by MH-E) will always search in all | |
201 | folders." | |
202 | (require 'mh-e) | |
203 | (require 'mh-search) | |
204 | (require 'mh-utils) | |
205 | (mh-find-path) | |
206 | (if (not article) | |
207 | (mh-visit-folder (mh-normalize-folder-name folder)) | |
20908596 CD |
208 | (mh-search-choose) |
209 | (if (equal mh-searcher 'pick) | |
33306645 | 210 | (progn |
b349f79f | 211 | (setq article (org-add-angle-brackets article)) |
33306645 CD |
212 | (mh-search folder (list "--message-id" article)) |
213 | (when (and org-mhe-search-all-folders | |
214 | (not (org-mhe-get-message-real-folder))) | |
215 | (kill-this-buffer) | |
216 | (mh-search "+" (list "--message-id" article)))) | |
b349f79f | 217 | (if mh-search-regexp-builder |
33306645 | 218 | (mh-search "+" (funcall mh-search-regexp-builder |
b349f79f | 219 | (list (cons 'message-id article)))) |
33306645 | 220 | (mh-search "+" article))) |
20908596 | 221 | (if (org-mhe-get-message-real-folder) |
33306645 | 222 | (mh-show-msg 1) |
20908596 CD |
223 | (kill-this-buffer) |
224 | (error "Message not found")))) | |
225 | ||
226 | (provide 'org-mhe) | |
227 | ||
228 | ;;; org-mhe.el ends here |