org-annotation-helper.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. ;;; org-annotation-helper.el --- start remember from a web browser
  2. ;;
  3. ;; Author: bzg AT altern DOT org
  4. ;; Author: dmg AT uvic DOT org
  5. ;;
  6. ;; Keywords: org remember
  7. ;;
  8. ;; Version 0.4, Feb 24, 2009
  9. ;; - Patch by David Moffat to force activation of region
  10. ;;
  11. ;; Version 0.3b, Sept 18, 2008
  12. ;; - Added one entry to FAQ
  13. ;;
  14. ;; Version 0.3a, June 3, 2008
  15. ;; - org-fied the FAQ, and fixed typos/grammar. Big thanks to Nick Dokos.
  16. ;; - Added a new file: README
  17. ;;
  18. ;; Version 0.3, May 23, 2008
  19. ;;
  20. ;; - Simplified call to org-remember by using %w template (thanks to Carsten
  21. ; Dominik)
  22. ;; - Improved documentation (thanks to Nick Dokos and John Rakestraw for this)
  23. ;; - Created a standalone file for the org-annotation-helper script
  24. ;; - Added org-annotation-helper.html with a FAQ and quick links to the bookmarkets
  25. ;;
  26. ;; Version 0.2, May 18, 2008
  27. ;;
  28. ;;; Commentary:
  29. ;;
  30. ;; [bzg:] This is an adapted version of the planner-mode extension the
  31. ;; was first posted by Geert Kloosterman <g.j.kloosterman@gmail.com> on
  32. ;; the Planner mailing list.
  33. ;;
  34. ;; [dmg:] I have updated and extended the function to allow for
  35. ;; handling of the selection (it is now available as a region, so it
  36. ;; can be used in a template using %:region )
  37. ;;
  38. ;;
  39. ;; We want to be able to pass a URL and document title directly from a
  40. ;; web browser to Emacs.
  41. ;;
  42. ;; The idea is to educate the browser about two new protocols "remember"
  43. ;; and "annotation", so that when it is asked to handle URLs with these
  44. ;; protocols, it will execute a shell script and pass some information
  45. ;; to it (the URL of the page it's on, the title and, in the case of the
  46. ;; remember protocol, the current selection on that page, if any.)
  47. ;;
  48. ;; The handlers are invoked using bookmarklets (fake bookmarks whose
  49. ;; "location" is some javascript code: when the bookmarklet is
  50. ;; activated, the javascript code is executed.) The bookmarklets
  51. ;; create remember:// or annotation:// URLs dynamically.
  52. ;;
  53. ;; When a handler is invoked, it executes a shell script to handle the
  54. ;; protocol and passes it the gathered information in a standard
  55. ;; format. The script, in turn, passes the information to a running
  56. ;; Emacs process (using emacsclient/gnuclient), calling the function
  57. ;; bzg/org-annotate-helper, which is what this file provides.
  58. ;;
  59. ;; The protocol types currently recognized and the corresponding actions
  60. ;; of bzg/org-annotate-helper are:
  61. ;;
  62. ;; remember:// assuming you have set up an appropriate remember
  63. ;; template (see below), start `remember' with the
  64. ;; url, title and current selection filled in
  65. ;;
  66. ;; annotation:// make an org link out of the url and the title and
  67. ;; glom it onto the kill ring, from where it can be
  68. ;; retrieved either with a yank or through
  69. ;; org-insert-link.
  70. ;;
  71. ;; The urls used internally have the following form:
  72. ;;
  73. ;; remember://<the web page url>::remember::<the title>::remember::<selection>
  74. ;;
  75. ;; or
  76. ;;
  77. ;; annotation://<the web page url>::remember::<the title>
  78. ;;
  79. ;; The url, title and selection (if present) will be url-hex-encoded.
  80. ;;
  81. ;;
  82. ;;======================================================================
  83. ;;
  84. ;; Here are the pieces you'll need, to set up the bits outside emacs.
  85. ;;
  86. ;;
  87. ;; The javascript code for the two bookmarklets:
  88. ;;
  89. ;;----------------------------------------------------------------------
  90. ;; javascript:location.href='remember://' + location.href + '::remember::' + escape(document.title) + '::remember::' + escape(window.getSelection())
  91. ;;----------------------------------------------------------------------
  92. ;; javascript:location.href='annotation://' + location.href + '::remember::' + escape(document.title)
  93. ;;----------------------------------------------------------------------
  94. ;;
  95. ;;
  96. ;; The shell script that the handlers execute:
  97. ;;
  98. ;;----------------------------------------------------------------------
  99. ;; #!/bin/sh
  100. ;; # org-annotation-helper -- pass a {remember,annotation}-url to emacs
  101. ;; #
  102. ;; # Author: Geert Kloosterman <g.j.kloosterman@gmail.com>
  103. ;; # Date: Sat Nov 19 22:33:18 2005
  104. ;;
  105. ;; if [ -z "$1" ]; then
  106. ;; echo "$0: Error: no arguments given!" 1>&2
  107. ;; exit 1
  108. ;; fi
  109. ;;
  110. ;; # To test uncomment following line
  111. ;; #echo $1 >> /tmp/remember.out
  112. ;;
  113. ;; emacsclient --eval "(progn (bzg/org-annotation-helper \"$1\" ) nil)"
  114. ;;----------------------------------------------------------------------
  115. ;;
  116. ;;
  117. ;;======================================================================
  118. ;;
  119. ;; Installation.
  120. ;;
  121. ;; Step 0: Install this module.
  122. ;;
  123. ;; * Install this file and require it in your .emacs:
  124. ;;
  125. ;; (require 'org-annotation-helper)
  126. ;;
  127. ;; * Add the following line to your .emacs if it's not there already:
  128. ;;
  129. ;; (server-start)
  130. ;;
  131. ;;
  132. ;; Step 1: Install the org-annotation-helper shell script and add
  133. ;; a remember template.
  134. ;;
  135. ;; * Save the shell script in a file in some directory in your $PATH,
  136. ;; and make sure it is executable. In the following, it is assumed
  137. ;; that the file name is "org-annotation-helper".
  138. ;;
  139. ;; * Add a ?w `remember template' to org-remember-templates. You can
  140. ;; start by using this template:
  141. ;;
  142. ;; (?w "* %u %c \n\n%:region" "~/working/trunk/org/bookmarks.org" "Web links")
  143. ;;
  144. ;; See section 9.2 of the Org manual for information about
  145. ;; `remember templates'.
  146. ;;
  147. ;; "%u" will be replaced by a timestamp, "%c" will be replaced with
  148. ;; the link to the page and labelled with the title of the page, and
  149. ;; "%:region" will be replaced with the selected text from the
  150. ;; browser. By default, the new remember notes are placed in the
  151. ;; bookmarks.org file under the "Web links" section, but that can be
  152. ;; easily overriden with C-u C-c C-c.
  153. ;;
  154. ;; * Try the setup so far:
  155. ;;
  156. ;; Make sure emacs is running and you have started its server
  157. ;; mode: ``M-x server-start<RET>'' should do it.
  158. ;;
  159. ;; Run this command from the command line:
  160. ;;
  161. ;; org-annotation-helper 'remember://http%3A//orgmode.org/::remember::Org-Mode%20Homepage::remember::Notes'
  162. ;;
  163. ;; Assuming you used the template above, you should be looking at
  164. ;; a *Remember* buffer that looks like this (minor variations are
  165. ;; possible because of local customizations - the last three lines
  166. ;; of the output are the important one and should be identical):
  167. ;; ## Filing location: Select interactively, default, or last used:
  168. ;; ## C-u C-c C-c to select file and header location interactively.
  169. ;; ## C-c C-c "~/working/trunk/org/bookmarks.org" -> "* Web links"
  170. ;; ## C-u C-u C-c C-c "~/working/trunk/org/bookmarks.org" -> "* Web links"
  171. ;; ## To switch templates, use `C-c r'. To abort use `C-c C-k'.
  172. ;;
  173. ;; * [2008-05-21 Wed] [[http://orgmode.org/][Org-Mode Homepage]]
  174. ;;
  175. ;; Notes
  176. ;; Assuming that everything is OK, the script and emacs side of the setup are done.
  177. ;;
  178. ;;
  179. ;; Step 2: Browser set-up - add two bookmarklets.
  180. ;;
  181. ;; Note: see the file org-annotation-helper-faq.html for a simpler way to add
  182. ;; these bookmarklets
  183. ;;
  184. ;; [Firefox specific]
  185. ;;
  186. ;; * Create a new bookmark, e.g by selecting Bookmarks/Organize bookmarks... and clicking
  187. ;; on "New Bookmark". In the "Properties" pop-up, give it a unique name.
  188. ;; * In the "Location" field, fill in the first line of javascript code above.
  189. ;; * Make sure "Load this bookmark in the sidebar" is deselected and click "OK".
  190. ;;
  191. ;; * Lather, rinse, repeat for the second line of javascript code.
  192. ;;
  193. ;; Try the two bookmarklets. You should get error pop-ups about
  194. ;; unknown protocols "remember" or "annotation", because your browser
  195. ;; will not know what do to with them yet (but see the Firefox 3
  196. ;; section below, if you are running that browser).
  197. ;;
  198. ;; You can also look at org-annotation-helper.html for a simple way to add both.
  199. ;;
  200. ;; Step 3: Browser set-up - add the protocol handlers for the
  201. ;; "remember://" and "annotation://" URIs.
  202. ;;
  203. ;; [Firefox]
  204. ;;
  205. ;; To add a protocol handler (eg: remember://) in Firefox, take the
  206. ;; following steps:
  207. ;;
  208. ;; * For Firefox 2, type "about:config" in the location bar, right
  209. ;; click to get the pop-up menu, select New --> String, and in the
  210. ;; name field, enter "network.protocol-handler.app.remember".
  211. ;;
  212. ;; In Firefox 3, when you first click on the button associated with
  213. ;; the bookmarklet, you should get a pop-up asking if you'd like to
  214. ;; associate the bookmarklet with a particular file. Use the
  215. ;; file-select process to navigate to the org-annotation-helper
  216. ;; script and select it. You can still edit the about:config
  217. ;; list directly as in Firefox 2.
  218. ;;
  219. ;; * the value should be the name of the file containing the shell
  220. ;; script, e.g. in Step 1, we called it "org-annotation-helper".
  221. ;; At least under Linux this does not need to be the full path to
  222. ;; the script.
  223. ;;
  224. ;;
  225. ;; * Lather, rinse, repeat for the annotation protocol. The string to
  226. ;; add is, in this case, "network.protocol-handler.app.annotation",
  227. ;; and the script is the same as
  228. ;;
  229. ;; You should have two new entries like this:
  230. ;;
  231. ;; network.protocol-handler.app.annotation user set string <path>
  232. ;; network.protocol-handler.app.remember user set string <path>
  233. ;;
  234. ;; where <path> is the location where org-annotation-helper is
  235. ;; for example, in my case it is /home/dmg/bin/org-annotation-helper
  236. ;; See http://kb.mozillazine.org/Register_protocol for more details.
  237. ;;
  238. ;; [Opera]
  239. ;;
  240. ;; In Opera add the protocol in the Preferences->Advanced->Programs
  241. ;; dialog.
  242. ;;
  243. ;;
  244. ;; Step 4: At this point, activating the bookmarklets should invoke
  245. ;; the shell script, which will invoke the
  246. ;; bzg/org-annotation-helper function (below), which will do one of
  247. ;; two things: for a remember:// URL, it will bring up a *Remember*
  248. ;; buffer; for an annotation:// URL, it will squirrel away a link
  249. ;; that you can use with C-c C-l.
  250. ;;
  251. ;;
  252. ;; Debugging notes: if there are problems, it might be useful to run
  253. ;; the shell script from the command line (see Step 1 above); it might
  254. ;; also be useful to uncomment the "echo" line in the shell
  255. ;; script. That will dump the script's argument in /tmp/remember.out,
  256. ;; so you can figure out if the browser is passing the right stuff to
  257. ;; the script. If it does pass the right stuff, then the emacs side
  258. ;; probably has a problem; if not, then the browser side is the likely
  259. ;; suspect.
  260. (require 'url)
  261. (autoload 'url-unhex-string "url")
  262. (defun bzg/org-annotation-helper (info)
  263. "Process an externally passed remember:// style url.
  264. URLSTRING consists of a protocol part and a url and title,
  265. separated by ::remember::
  266. The protocol types currently recognized are:
  267. remember:// start `remember' with the url, title and selection (if any).
  268. annotation:// squirrel away a link of the form [[url][title]] that can
  269. be used later with \\[org-insert-link]."
  270. (interactive)
  271. (let ((remember-annotation-functions nil))
  272. ;; The `parse-url' functions break on the embedded url,
  273. ;; since our format is fixed we'll split the url ourselves.
  274. (if (string-match "^\\([^:]*\\):\\(/*\\)\\(.*\\)" info)
  275. (let* ((b (get-buffer-create "*org-ann*"))
  276. (proto (match-string 1 info))
  277. (url_title_region (match-string 3 info))
  278. (splitparts (split-string url_title_region "::remember::"))
  279. (url (url-unhex-string (car splitparts)))
  280. (type (if (string-match "^\\([a-z]+\\):" url)
  281. (match-string 1 url)))
  282. (title (cadr splitparts))
  283. (region (url-unhex-string (caddr splitparts)))
  284. orglink)
  285. (setq title (if (> (length title) 0) (url-unhex-string title)))
  286. (setq orglink (org-make-link-string url title))
  287. (org-store-link-props :type type
  288. :link url
  289. :region region
  290. :description title)
  291. (setq org-stored-links
  292. (cons (list url title) org-stored-links))
  293. ;; FIXME can't access %a in the template -- how to set annotation?
  294. (raise-frame)
  295. (cond ((equal proto "remember")
  296. (kill-new orglink)
  297. (set-buffer b)
  298. (set-mark (point))
  299. (insert region)
  300. (exchange-point-and-mark t) ;; activate region.. not always on by default
  301. (org-remember nil ?w)
  302. (kill-buffer b)
  303. )
  304. ((equal proto "annotation")
  305. (message "Copied '%s' to the kill-ring." orglink)
  306. (kill-new orglink))
  307. (t (error "unrecognized org-helper protocol"))))
  308. (error "could not parse argument")))
  309. )
  310. (provide 'org-annotation-helper)