muse-protocols: Add Wikipedia support.
[muse-el.git] / lisp / muse-protocols.el
blob12e253769eceea369e257468e4aa0eac857093d0
1 ;;; muse-protocols.el --- URL protocols that Muse recognizes
3 ;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
5 ;; This file is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 2, or (at your option)
8 ;; any later version.
10 ;; This file is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with GNU Emacs; see the file COPYING. If not, write to the
17 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 ;; Boston, MA 02110-1301, USA.
20 ;;; Commentary:
22 ;; Here's an example for adding a protocol for the site yubnub, a Web
23 ;; Command line service.
25 ;; (add-to-list 'muse-url-protocols '("yubnub://" muse-browse-url-yubnub
26 ;; muse-resolve-url-yubnub))
28 ;; (defun muse-resolve-url-yubnub (url)
29 ;; "Resolve a yubnub URL."
30 ;; ;; Remove the yubnub://
31 ;; (when (string-match "\\`yubnub://\\(.+\\)" url)
32 ;; (match-string 1)))
34 ;; (defun muse-browse-url-yubnub (url)
35 ;; "If this is a yubnub URL-command, jump to it."
36 ;; (setq url (muse-resolve-url-yubnub url))
37 ;; (browse-url (concat "http://yubnub.org/parser/parse?command="
38 ;; url)))
40 ;;; Contributors:
42 ;; Brad Collins (brad AT chenla DOT org) created the initial version
43 ;; of this.
45 ;; Phillip Lord (Phillip.Lord AT newcastle DOT ac DOT uk) provided a
46 ;; handler for DOI URLs.
48 ;;; Code:
50 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
52 ;; Muse URL Protocols
54 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56 (require 'info)
57 (require 'muse-regexps)
59 (defvar muse-url-regexp nil
60 "A regexp used to match URLs within a Muse page.
61 This is autogenerated from `muse-url-protocols'.")
63 (defun muse-update-url-regexp (sym value)
64 (setq muse-url-regexp
65 (concat "\\<\\(" (mapconcat 'car value "\\|") "\\)"
66 "[^][" muse-regexp-blank "\"'()<>^`{}\n]*"
67 "[^][" muse-regexp-blank "\"'()<>^`{}.,;\n]+"))
68 (set sym value))
70 (defcustom muse-url-protocols
71 '(("info://" muse-browse-url-info nil)
72 ("man://" muse-browse-url-man nil)
73 ("google://" muse-browse-url-google muse-resolve-url-google)
74 ("http:/?/?" browse-url identity)
75 ("https:/?/?" browse-url identity)
76 ("ftp:/?/?" browse-url identity)
77 ("gopher://" browse-url identity)
78 ("telnet://" browse-url identity)
79 ("wais://" browse-url identity)
80 ("file://?" browse-url identity)
81 ("dict:" muse-browse-url-dict muse-resolve-url-dict)
82 ("doi:" muse-browse-url-doi muse-resolve-url-doi)
83 ("news:" browse-url identity)
84 ("snews:" browse-url identity)
85 ("mailto:" browse-url identity))
86 "A list of (PROTOCOL BROWSE-FUN RESOLVE-FUN) used to match URL protocols.
87 PROTOCOL describes the first part of the URL, including the
88 \"://\" part. This may be a regexp.
90 BROWSE-FUN should accept URL as an argument and open the URL in
91 the current window.
93 RESOLVE-FUN should accept URL as an argument and return the final
94 URL, or nil if no URL should be included."
95 :type '(repeat (list :tag "Protocol"
96 (string :tag "Regexp")
97 (function :tag "Browse")
98 (choice (function :tag "Resolve")
99 (const :tag "Don't resolve" nil))))
100 :set 'muse-update-url-regexp
101 :group 'muse)
103 (defcustom muse-wikipedia-country "en"
104 "Indicate the 2-digit country code that we use for Wikipedia
105 queries."
106 :type 'string
107 :options '("de" "en" "es" "fr" "it" "pl" "pt" "ja" "nl" "sv")
108 :group 'muse)
110 (defun muse-protocol-find (proto list)
111 "Return the first element of LIST whose car matches the regexp PROTO."
112 (setq list (copy-alist list))
113 (let (entry)
114 (while list
115 (when (string-match (caar list) proto)
116 (setq entry (car list)
117 list nil))
118 (setq list (cdr list)))
119 entry))
121 ;;;###autoload
122 (defun muse-browse-url (url &optional other-window)
123 "Handle URL with the function specified in `muse-url-protocols'.
124 If OTHER-WINDOW is non-nil, open in a different window."
125 (interactive (list (read-string "URL: ")
126 current-prefix-arg))
127 ;; Strip text properties
128 (when (fboundp 'set-text-properties)
129 (set-text-properties 0 (length url) nil url))
130 (when other-window
131 (switch-to-buffer-other-window (current-buffer)))
132 (when (string-match muse-url-regexp url)
133 (let* ((proto (concat "\\`" (match-string 1 url)))
134 (entry (muse-protocol-find proto muse-url-protocols)))
135 (when entry
136 (funcall (cadr entry) url)))))
138 (defun muse-resolve-url (url &rest ignored)
139 "Resolve URL with the function specified in `muse-url-protocols'."
140 (when (string-match muse-url-regexp url)
141 (let* ((proto (concat "\\`" (match-string 1 url)))
142 (entry (muse-protocol-find proto muse-url-protocols)))
143 (when entry
144 (let ((func (car (cddr entry))))
145 (if func
146 (setq url (funcall func url))
147 (setq url nil))))))
148 url)
150 (defun muse-protocol-add (protocol browse-function resolve-function)
151 "Add PROTOCOL to `muse-url-protocols'. PROTOCOL may be a regexp.
153 BROWSE-FUNCTION should be a function that visits a URL in the
154 current buffer.
156 RESOLVE-FUNCTION should be a function that transforms a URL for
157 publishing or returns nil if not linked."
158 (add-to-list 'muse-url-protocols
159 (list protocol browse-function resolve-function))
160 (muse-update-url-regexp 'muse-url-protocols
161 muse-url-protocols))
163 (defun muse-resolve-url-dict (url)
164 "Return the Wikipedia link corresponding with the given URL."
165 (when (string-match "\\`dict:\\(.+\\)" url)
166 (concat "http://" muse-wikipedia-country ".wikipedia.org/"
167 "wiki/Special:Search?search=" (match-string 1 url))))
169 (defun muse-browse-url-dict (url)
170 "If this is a Wikipedia URL, browse it."
171 (let ((dict-url (muse-resolve-url-dict url)))
172 (when dict-url
173 (browse-url dict-url))))
175 (defun muse-resolve-url-doi (url)
176 "Return the URL through DOI proxy server."
177 (when (string-match "\\`doi:\\(.+\\)" url)
178 (concat "http://dx.doi.org/"
179 (match-string 1 url))))
181 (defun muse-browse-url-doi (url)
182 "If this is a DOI URL, browse it.
184 DOI's (digitial object identifiers) are a standard identifier
185 used in the publishing industry."
186 (let ((doi-url (muse-resolve-url-doi url)))
187 (when doi-url
188 (browse-url doi-url))))
190 (defun muse-resolve-url-google (url)
191 "Return the correct Google search string."
192 (when (string-match "\\`google:/?/?\\(.+\\)" url)
193 (concat "http://www.google.com/search?q="
194 (match-string 1 url))))
196 (defun muse-browse-url-google (url)
197 "If this is a Google URL, jump to it."
198 (let ((google-url (muse-resolve-url-google url)))
199 (when google-url
200 (browse-url google-url))))
202 (defun muse-browse-url-info (url)
203 "If this in an Info URL, jump to it."
204 (require 'info)
205 (cond
206 ((string-match "\\`info://\\([^#\n]+\\)#\\(.+\\)" url)
207 (Info-find-node (match-string 1 url)
208 (match-string 2 url)))
209 ((string-match "\\`info://\\([^#\n]+\\)" url)
210 (Info-find-node (match-string 1 url)
211 "Top"))
212 ((string-match "\\`info://(\\([^)\n]+\\))\\(.+\\)" url)
213 (Info-find-node (match-string 1 url) (match-string 2 url)))
214 ((string-match "\\`info://\\(.+\\)" url)
215 (Info-find-node (match-string 1 url) "Top"))))
217 (defun muse-browse-url-man (url)
218 "If this in a manpage URL, jump to it."
219 (cond ((string-match "\\`man://\\(.+\\):\\(.+\\)" url)
220 (manual-entry (concat (match-string 1 url)
221 "(" (match-string 2 url) ")")))
222 ((string-match "\\`man://\\(.+\\)" url)
223 (manual-entry (concat (match-string 1 url))))))
225 (provide 'muse-protocols)
227 ;;; muse-protocols.el ends here