1 #+TITLE: org-protocol.el -- Intercept calls from emacsclient to trigger custom actions
2 #+OPTIONS: H:3 num:nil toc:t \n:nil @:t ::t |:t -:t f:t *:t TeX:t LaTeX:t skip:nil d:(HIDE) tags:not-in-toc ^:{} author:nil
4 #+STYLE: <script type="text/javascript">
5 #+STYLE: <!--/*--><![CDATA[/*><!--*/
6 #+STYLE: function makeUrl() {
7 #+STYLE: return encodeURIComponent(location.href)+
8 #+STYLE: '/'+encodeURIComponent(document.title)+
9 #+STYLE: '/'+encodeURIComponent(window.getSelection());
11 #+STYLE: function storeLink() {
12 #+STYLE: document.location.href='org-protocol://store-link://'+makeUrl();
14 #+STYLE: function remember() {
15 #+STYLE: document.location.href='org-protocol://remember://'+makeUrl();
20 [[file:index.org][{Back to Worg's contibutions index}]]
22 org-protocol intercepts calls from emacsclient to trigger custom actions without
23 external dependencies. Only one protocol has to be configured with your external
24 applications or the operating system, to trigger an arbitrary number of custom
25 actions. Just register your custom sub-protocol and handler with the variable
26 `org-protocol-protocol-alist'.
29 * About org-protocol.el
31 =org-protocol.el= is based on code and ideas from [[file:./org-annotation-helper.org][org-annotation-helper.el]] and
34 "=org-protocol:/sub-protocol:/=" triggers actions assossiated with =sub-protocol=
35 through the custom variable =org-protocol-protocol-alist=.
37 It comes with three predefined handlers:
38 - =org-protocol-store-link= ::
39 triggered through the sub-protocol "=store-link=". Stores an Org-link and
40 pushes the URL to the =kill-ring=.
41 - =org-protocol-remember= ::
42 Fill a remember buffer with informations gathered somewhere else. This one
43 is triggered through the "=remember=" sub-protocol.
44 - =org-protocol-open-source= ::
45 "=open-source=". Maps URLs to local filenames. Use this to open sources of
46 already published contents in emacs for editing.
48 =org-protocol= helps creating custom handlers [[file:../org-tutorials/org-protocol-custom-handler.org][(tutorial)]] and so called
49 =org-protocol-projects=.
55 - To load org-protocol.el add the following to your =.emacs=:
58 : (add-to-list 'load-path "~/path/to/org/protocol/")
59 : (require 'org-protocol)
61 * Browser / system setup
63 Windows users proceed to the section [[windows-setup][Windows]].
68 As of March 2009 Firefox users follow the steps documented on
69 http://kb.mozillazine.org/Register_protocol. Here is a summary:
71 1. Type "=about:config=" into the location bar and press enter.
72 2. Click "/I'll be careful, I promise!/" to continue.
73 3. Right-click on the grid
74 4. Choose "/New/" -> "/String/" from the context menu.
75 5. Enter "=network.protocol-handler.app.org-protocol=" as the properties name.
77 7. Leave the value blank.
78 8. Next time you try to open a location "=org-protocol://...=" FF will ask you for
79 the program to use. Enter the path to emacsclient.
84 :CUSTOM_ID: acrobat-reader-setup
87 Adapted from [[http://article.gmane.org/gmane.emacs.orgmode/6810]]
89 You place a javascript file for each menu entry in
90 =~/.adobe/Acrobat/<VERSION>/JavaScripts= on unix-like systems or
91 =c:/Program Files/Adobe/Acrobat <VERSION>/Reader/Javascripts/= on
92 Windows, or wherever your Adobe Reader Installation might look for
95 The examples given here will place new menu entries in the "Tools"
96 menu, after restarting Adobe Reader.
98 # <<acrobat-store-link-js>>
99 ***** org-store-link.js
100 : // from http://article.gmane.org/gmane.emacs.orgmode/6810
101 : app.addMenuItem({cName:"org-store-link", cParent:"Tools",
102 : cExec:"app.launchURL('org-protocol://store-link://' + encodeURIComponent(this.URL) + '/' + encodeURIComponent(this.info.Title));"});
104 # <<acrobat-remember-js>>
105 ***** org-remember.js
106 : // from http://article.gmane.org/gmane.emacs.orgmode/6810
107 : app.addMenuItem({cName:"org-remember", cParent:"Tools",
108 : cExec:"app.launchURL('org-protocol://remember://' + encodeURIComponent(this.URL) + '/' + encodeURIComponent(this.info.Title) + '/');"});
114 Opera setup is described here:
115 http://www.opera.com/support/kb/view/535/.
117 To set up opera for use with org-protocol, follow these steps:
119 1. Choose "/Tools/" -> "/Prefences/" from the menu.
120 2. Select the tab "/Advanced/".
121 3. Choose "/Programs/" from the list on the left.
122 4. Now click the button "/Add/" on the very right.
123 5. In the new dialog window, enter "=org-protocol=" as "/Protocol/", choose the
124 radio button "/Open with other application/" and enter the path to
130 Windows users may register the "=org-protocol=" once for all by adjusting the
131 following to their facts, save it as *.reg file and double-click it. This
132 worked for me on Windows-XP Professional and the emasc23 from ourcomments.org
133 ([[http://ourcomments.org/cgi-bin/emacsw32-dl-latest.pl]]). I'm no Windows user
134 though and enhancements are more than welcome on the org-mode mailinglist. The
135 original file is from http://kb.mozillazine.org/Register_protocol.
140 [HKEY_CLASSES_ROOT\org-protocol]
143 [HKEY_CLASSES_ROOT\org-protocol\shell]
144 [HKEY_CLASSES_ROOT\org-protocol\shell\open]
145 [HKEY_CLASSES_ROOT\org-protocol\shell\open\command]
146 @="\"C:\\Programme\\Emacs\\emacs\\bin\\emacsclientw.exe\" \"%1\""
150 # <<test-org-protocol>>
151 *** Verify the installation
153 After your protocol is registered with your browse/OS, these links here
154 should work. Click on them and see if emacs reacts:
158 <li><a href="javascript:storeLink();">Org store-link</a></li>
159 <li><a href="javascript:remember();">Org remember (select some text please)</a></li>
164 # <<default-location>>
167 To actually use org-protocol add a bookmark to Firefox or opera.
169 Here is the URL to use as "/Location/" for browser bookmarks. Just remove the
170 line breaks and replace "=sub-protocol=" with the real sub-protocol to use:
172 : javascript:location.href='org-protocol://sub-protocol://'+
173 : encodeURIComponent(location.href)+'/'+
174 : encodeURIComponent(document.title)+'/'+
175 : encodeURIComponent(window.getSelection())
177 This URL may be used for all three standard handlers in =org-protocol.el=. Some
178 of the values will be ignored (e.g. =store-link:/= will use the URL and title
181 # <<org-protocol-store-link>>
182 * Links and bookmarks: =org-protocol-store-link=
184 =org-store-link= stores an Org-link insertable through =M-x org-insert-link= and
185 pushes the URL found on the =kill-ring= for yanking (=C-y=). The sub-protocol used
188 : emacsclient org-protocol:/store-link:/URL/TITLE
190 will store this Org-link:
196 In addition, =URL= will be pushed on the =kill-ring= for yanking ('=C-y='). You will
197 have to encode =URL= and/or =TITLE= if they contain slashes, and probably quote
200 To use this feature, add a bookmark with an arbitrary name (e.g.
201 "/Org: store-link/") and enter this as "=Location=":
203 : javascript:location.href='org-protocol://store-link://'+encodeURIComponent(location.href)
206 # <<org-protocol-remember>>
207 * Note taking and citations: =org-protocol-remember=
209 This one is triggered through the sub-protocol "=remember=" and consumes up to
212 : emacsclient org-protocol:/remember:/URL/TITLE/BODY
214 will pop up an /*Remember*/ buffer and fill the template with the data
217 To use this feature, add a bookmark with an arbitrary name (e.g.
218 "/Org: remember/") and enter this as "=Location=":
220 : javascript:location.href='org-protocol://remember://'+
221 : encodeURIComponent(location.href)+'/'+
222 : encodeURIComponent(document.title)+'/'+
223 : encodeURIComponent(window.getSelection())
225 The result depends on the template used. See [[example-template][An example remember template]]
228 Note, that this one, as opposed to the other two standard handlers, does not
229 mix with more parameters to emacsclient. All parameters but the
230 #'=org-protocol://org-remember://...=' one will be discarded.
232 # <<which-remember-template>>
233 *** Which remember template is used?
235 You don't need to setup a remember template to use =org-protocol-remember=,
236 since Org-mode provides a default template for those cases. But, for
237 historical reasons, if a template with the template char '=?w=' is defined,
238 this one will be choosen by default. This is to make bookmarks used for
239 [[file:./org-annotation-helper.el][org-annotation-helper]] work without changing the template.
241 The problem with this solution would be, that only one template can be used
242 with the fuction. Luckily, =org-protocol-remember= understands a slightly
243 extended syntax to choose between several templates: If the first field of
244 the data submitted is exactly one character in length, this character will
245 be used to select the template.
247 Here we choose to use the '=?x=' template:
249 : emacsclient org-protocol:/remember:/x/URL/TITLE/BODY
251 And, again, as bookmark location:
252 : javascript:location.href='org-protocol://remember://x/'+
253 : encodeURIComponent(location.href)+'/'+
254 : encodeURIComponent(document.title)+'/'+
255 : encodeURIComponent(window.getSelection())
257 # <<example-template>>
258 *** An example remember template
260 #+begin_src emacs-lisp
261 (setq org-remember-templates
262 '((?w "* %^{Title}\n\n Source: %u, %c\n\n %i" nil "Notes")))
265 - '=?w=' :: makes this one the default template used for
266 "=org-protocol://remember://=" URLs.
267 - '=%c=' :: will be replaced by an Org-link pointing to the location of the
268 page you have been visiting when clicking on the link. The page
269 title will be the links description.
270 - '=%i=' :: will be replaced by the selected text in your browser window if
273 In addition, you may use the following placeholders in your template:
275 | Placeholders | Replacement |
276 |---------------+---------------------------|
277 | =%:link= | URL of the web-page |
278 | =%:description= | The title of the web-page |
279 | =%:initial= | Selected text. |
281 You may read more about templates and their special escape characters in the
282 [[http://orgmode.org/manual/Remember-templates.html#Remember-templates][Org-mode manual]].
286 * Edit published content: =org-protocol-open-source=
288 This one was designed to help with opening sources for editing when browsing
289 in the first place. =org-protocol-open-source= uses the custom variable
290 =org-protocol-project-alist= to map URLs to (local) filenames.
292 Let's take http://orgmode.org/worg/ as our example.
294 Our intention is to click a bookmark (or link) to open the source of the
295 published file we are reading in our favourite editor. The bookmark-URL above
296 could be used again. But since =org-protocol-open-source= regards the first
297 field only, this here will do:
299 : javascript:location.href='org-protocol://open-source://'+encodeURIComponent(location.href)
301 To open files publihed on Worg locally, =org-protocol-project-alist= should look
302 like this (you may skip the second project):
304 #+begin_src emacs-lisp
305 (setq org-protocol-project-alist
307 :base-url "http://orgmode.org/worg/"
308 :working-directory "/home/user/worg/"
309 :online-suffix ".html"
310 :working-suffix ".org")
311 ("My local Org-notes"
312 :base-url "http://localhost/org/"
313 :working-directory "/home/user/org/"
314 :online-suffix ".php"
315 :working-suffix ".org")))
318 If you're now browsing http://orgmode.org/worg/org-tutorials/org-protocol.php
319 and find a typo or have an idea how to enhance the documentation, simply click
320 the bookmark and start editing.
322 There are to functions to help you filling =org-protocol-project-alist= with
323 valid contents. First of which is =org-protocol-create= that guides you through
324 the process. If you're editing an Org-mode file that is part of a publishing
325 project in =org-publish-project-alist=, try
327 : M-x org-protocol-create-for-org RET
329 # <<open-source-rewritten-urls>>
330 *** Handle rewritten URLs
332 In some cases, replacing =:base-url= with =:working-directory= and
333 =:online-suffix= with =:working-suffix= will not yield the desired results.
335 Suppose you maintain an online store located at =http://example.com/=. The
336 local sources reside in =/home/user/example/=. While most of the URLs map
337 directly to local file names by stripping URL parameters from the end and
338 replacing the =:base-url= with =:working-diretory= and =:online-suffix= with
339 =working-suffix=, this might not work for rewritten URLs. It's common
340 practice, to serve all products in such a store through one file and rewrite
341 URLs, that do not match an existing file on the server.
343 That way, a request to =http://example.com/print/posters-A4.html= might be
344 rewritten on the server to something like
345 =http://example.com/shop/products.php/posters-A4.html.php=, where
346 =/posters-A4-digital.html.php= is the so called path info. Note, that the
347 browser will not notice the rewrite.
349 If you now click your =org-protocol://open-source://= bookmark, the handler
350 will probably not find a file named
351 =/home/user/example/print/posters-A4.html.php= and fail.
353 Or, even more simple, assume your browsing to =http://example.com/=. A file
354 named =/home/user/example/.php= is not likely to exist.
356 Since Org-mode commit =69b46e10aab3b2374ecbc1a963ba56e77102a9a4= from 15nth
357 Nov. 2009, such an entry in =org-protocol-project-alist= may hold an
358 additional property =:rewrites=. This property is a list of cons cells, each
359 of which maps a regular expression to a path, relative to the
360 =:working-directory=.
362 Now map the URL to the path =/home/user/example/products.php= by adding the
363 =:rewrites= property like this:
365 #+begin_src emacs-lisp
366 (setq org-protocol-project-alist
368 :base-url "http://example.com/"
369 :working-directory "/home/user/example/"
370 :online-suffix ".php"
371 :working-suffix ".php"
372 :rewrites (("example.com/print/" . "products.php")
373 ("example.com/$" . "index.php"))
377 Guess what the second =:rewrites= element does. Since =example.com/$= is used as
378 a regular expression, it maps =http://example.com/=, =https://example.com=,
379 =http://www.example.com/= and similar to =/home/user/example/index.php=.
381 The =:rewrites= are searched as a last resort if, and only if no existing file
388 Setting up org-protocol in [[http://conkeror.org/][Conkeror]] (an emacs inspired Mozilla web
389 browser) requires a slightly different method. You may simply add the
390 following snippets of code to your .conkerorrc file.[fn:tassilosblog]
392 For org-store-link, add the following to .conkerorrc:
394 : function org_store_link (url, title, window) {
395 : var cmd_str = 'emacsclient \"org-protocol://store-link://'+url+'/'+title+'\"';
396 : if (window != null) {
397 : window.minibuffer.message('Issuing ' + cmd_str);
399 : shell_command_blind(cmd_str);
402 : interactive("org-store-link", "Stores [[url][title]] as org link and copies url to emacs kill ring",
404 : org_store_link(encodeURIComponent(I.buffer.display_uri_string), encodeURIComponent(I.buffer.document.title), I.window);
407 For org-remember, use the following:
409 : function org_remember (url, title, selection, window) {
410 : var cmd_str = 'emacsclient \"org-protocol://remember://'+url+'/'+title+'/'+selection+'\"';
411 : if (window != null) {
412 : window.minibuffer.message('Issuing ' + cmd_str);
414 : shell_command_blind(cmd_str);
417 : interactive("org-remember", "Clip url, title, and selection to remember via org-protocol",
419 : org_remember(encodeURIComponent(I.buffer.display_uri_string), encodeURIComponent(I.buffer.document.title), encodeURIComponent(I.buffer.top_frame.getSelection()), I.window);
422 Now, you should be able to invoke the commands from within conkeror
423 with =M-x org-store-link= and =M-x org-remember=.
425 Or, if you'd like your familiar emacs keybindings, you can add the
426 following to your .conkerorrc:
428 : define_key(content_buffer_normal_keymap, "C-c r", "org-remember");
429 : define_key(content_buffer_normal_keymap, "C-c l", "org-store-link");
431 [fn:tassilosblog] Adapted from Tassilo Horn's blog, "Calling
432 org-remember from inside conkeror," November 14, 2008.
433 http://tsdh.wordpress.com/2008/11/14/calling-org-remember-from-inside-conkeror/
440 Uzbl is a minimalistic webkit browser for Unix/Linux.
442 - [[http://www.uzbl.org/]]
444 You can pass encoded url data from uzbl to org-protocol by adding the
445 following lines to =.config/uzbl/config=.
451 @cbind \\r = sh 'emacsclient "org-protocol://remember://\@<encodeURIComponent(window.location.href)>\@/\@<encodeURIComponent(document.title)>\@/\@<document.getSelection()>\@"'
452 @cbind \\l = sh 'emacsclient "org-protocol://remember://\@<encodeURIComponent(window.location.href)>\@/\@<encodeURIComponent(document.title)>\@"'
456 These bind org-protocol-remember and org-store-line to "\r" and "\l" respectively.
458 # <<firefox-keybindings>>
459 * Keybindings for Firefox
461 You can add key bindings for the =org-protocol= commands using the keyconfig
464 First, install keyconfig from http://mozilla.dorando.at/keyconfig.xpi.
466 Open the keyconfig dialog by going to Tools and then Keyconfig.
468 Click the 'Add a new Key' button. Enter "Org store link" as the name.
469 Enter the following in the box with /* CODE */ in it:
471 : var orgProtoString = 'org-protocol://store-link://'+
472 : encodeURIComponent(gBrowser.currentURI.spec) + '/' +
473 : encodeURIComponent(gBrowser.contentWindow.document.title) + '/' +
474 : encodeURIComponent(window.getSelection());
476 : gBrowser.loadURI(orgProtoString);
478 Click OK. You will then need to bind a key by clicking in the box next to the
479 'Apply' button and pressing whatever key combination you want. Click 'Apply' to
480 store the keybinding.
482 Repeat the steps, but call the next key "Org remember" and use the code below:
484 : var orgProtoString = 'org-protocol://remember://'+
485 : encodeURIComponent(gBrowser.currentURI.spec) + '/' +
486 : encodeURIComponent(gBrowser.contentWindow.document.title) + '/' +
487 : encodeURIComponent(window.getSelection());
489 : gBrowser.loadURI(orgProtoString);
491 Click Close, then OK, and then restart Firefox. You should then be able to
492 access the org-protocol functions with your chosen keys.
494 # <<screencast-intro>>
495 * Screencast: small introduction to org-protocol.el
498 <object width="640" height="464"><param name="allowfullscreen"
499 value="true" /><param name="allowscriptaccess" value="always" /><param
501 value="http://vimeo.com/moogaloop.swf?clip_id=5662410&server=vimeo.com&show_title=1&show_byline=1&show_portrait=1&color=FF7700&fullscreen=1"
503 src="http://vimeo.com/moogaloop.swf?clip_id=5662410&server=vimeo.com&show_title=1&show_byline=1&show_portrait=1&color=FF7700&fullscreen=1"
504 type="application/x-shockwave-flash" allowfullscreen="true"
505 allowscriptaccess="always" width="640" height="464"></embed></object>
508 This screencast shows off some nice things you can do with Firefox,
509 Emacs, Org-mode and org-protocol.el.
511 It first shows how to create two bookmarklets, =org-remember= and
512 =org-store-link=. These bookmarklets enable your Firefox to talk to
513 emacsclient via a new protocol (=org-protocol://=); emacsclient then
514 parses the request and tells Emacs to remember or store stuff at the
515 relevant places in your Org files.
517 At the end of the screencast, we create two ubiquity commands from these
518 bookmarklets. Now in Firefox =ALT-SPC org-remember RET= creates a note