Update copyright years again.
[org-mode.git] / contrib / scripts / org-docco.org
blobd846aa3a501bd8f46660486734fe6bbdd68c7120
1 #+Title: Org-Docco
2 #+Author: Eric Schulte
3 #+Style: <link rel="stylesheet" href="docco.css" type="text/css">
4 #+Property: tangle yes
6 The =docco= tool (see http://jashkenas.github.com/docco/) generates
7 HTML from JavaScript source code providing an attractive side-by-side
8 display of source code and comments.  This file (see [[http://orgmode.org/w/?p=org-mode.git;a=blob_plain;f=contrib/scripts/org-docco.org;hb=HEAD][org-docco.org]])
9 generates the same type of output from Org-mode documents with code
10 embedded in code blocks.
12 The way this works is an Org-mode document with embedded code blocks
13 is exported to html using the standard Org-mode export functions.
14 This file defines a new function named =org-docco-buffer= which, when
15 added to the =org-export-html-final-hook=, will be run automatically
16 as part of the Org-mod export process doccoizing your Org-mode
17 document.
19 A pure source code file can be extracted (or "/tangled/") from the
20 Org-mode document using the normal =org-babel-tangle= function.  See
21 [[http://orgmode.org/manual/Working-With-Source-Code.html][Working With Source Code]] chapter of the Org-mode manual for more
22 information on using code blocks in Org-mode files.
24 *Disclaimer*: this currently only works on /very/ simple Org-mode
25 files which have no headings but rather are just a collection of
26 alternating text and code blocks.  It wouldn't be difficult to
27 generalize the following code so that it could be run in particular
28 sub-trees but I simply don't have the time to do so myself, and this
29 version perfectly satisfies my own limit needs.  I make no promises to
30 support this code moving forward.  /Caveat Emptor/
32 #+begin_src emacs-lisp :padline no
33 ;;; org-docco.el --- docco type html generation from Org-mode
35 ;; Copyright (C) 2012 Eric Schulte
37 ;; Author: Eric Schulte
38 ;; Keywords: org-mode, literate programming, html
39 ;; Homepage: http://orgmode.org/worg/org-contrib/org-mime.php
40 ;; Version: 0.01
42 ;; This file is not part of GNU Emacs.
44 ;;; License:
46 ;; This program is free software; you can redistribute it and/or modify
47 ;; it under the terms of the GNU General Public License as published by
48 ;; the Free Software Foundation; either version 3, or (at your option)
49 ;; any later version.
51 ;; This program is distributed in the hope that it will be useful,
52 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
53 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54 ;; GNU General Public License for more details.
56 ;; You should have received a copy of the GNU General Public License
57 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
58 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
59 ;; Boston, MA 02110-1301, USA.
61 ;;; Commentary:
63 ;; <- look over there
64 #+end_src
66 The =cl= package provides all of the state-changing functions used
67 below e.g., =push= and =incf=.  It looks like a namespace-safe version
68 of =cl= may soon be permissible for use in official Emacs packages.
69 #+begin_src emacs-lisp
70 ;;; Code:
71 (require 'cl)
72 #+end_src
74 This is a function which returns the buffer positions of matching
75 regular expressions.  It has two special features...
76 1. It only counts matched instances of =beg-re= and =end-re= which are
77    properly nested, so for example if =beg-re= and =end-re= are set to
78    =(= and =)= respectively and we run this against the following,
79    : 1    2       3 4   5     6
80    : |    |       | |   |     |
81    : v    v       v v   v     v
82    : (foo (bar baz) (qux) quux)
83    it will return 1 and 6 rather than 1 and 3.
84 2. It uses [[www.gnu.org/s/emacs/manual/html_node/elisp/Markers.html][markers]] which save their position in a buffer even as the
85    buffer is changed (e.g., by me adding in extra HTML text).
86 #+begin_src emacs-lisp
87 (defun org-docco-balanced-re (beg-re end-re)
88   "Return the beginning and of a balanced regexp."
89   (save-excursion
90     (save-match-data
91       (let ((both-re (concat "\\(" beg-re "\\|" end-re "\\)"))
92             (beg-count 0) (end-count 0)
93             beg end)
94         (when (re-search-forward beg-re nil t)
95           (goto-char (match-beginning 0))
96           (setq beg (point-marker))
97           (incf beg-count)
98           (goto-char (match-end 0))
99           (while (and (not end) (re-search-forward both-re nil t))
100             (goto-char (match-beginning 0))
101             (cond ((looking-at beg-re) (incf beg-count))
102                   ((looking-at end-re) (incf end-count))
103                   (:otherwise (error "miss-matched")))
104             (goto-char (match-end 0))
105             (when (= beg-count end-count) (setq end (point-marker))))
106           (when end (cons beg end)))))))
107 #+end_src
109 This ugly large function does the actual conversion.  It wraps the
110 entire main content =div= of the exported Org-mode html into a single
111 large table.  Each row of the table has documentation on the left side
112 and code on the right side.  This function has two parts.
113 1. We use =(org-docco-balanced-re "<div" "</div>")= to find the
114    beginning and end of the main content div.  We then break up this
115    div at =<pre></pre>= boundaries with multiple calls to
116    =(org-docco-balanced-re "<pre class\"src" "</pre>")=.
117 2. With all documentation/code boundaries in hand we step through the
118    buffer inserting the table html code at boundary locations.
119 #+begin_src emacs-lisp
120 (defun org-docco-buffer ()
121   "Call from within an HTML buffer to doccoize it."
122   (interactive)
123   (let ((table-start "<table>\n")
124         (doc-row-start  "<tr><th class=\"docs\">\n") (doc-row-end  "</th>\n")
125         (code-row-start "    <td class=\"code\">\n") (code-row-end "</td></tr>\n")
126         (table-end "</table>" )
127         pair transition-points next)
128     (save-excursion
129       (save-match-data
130         (goto-char (point-min))
131         (when (re-search-forward "<div id=\"content\">" nil t)
132           (goto-char (match-end 0))
133           (push (point-marker) transition-points)
134           (goto-char (match-beginning 0))
135           (setq pair (org-docco-balanced-re "<div" "</div>"))
136           (while (setq next (org-docco-balanced-re "<pre class=\"src" "</pre>"))
137             (goto-char (cdr next))
138             (push (car next) transition-points)
139             (push (cdr next) transition-points))
140           (goto-char (cdr pair))
141           (push (and (re-search-backward "</div>" nil t) (point-marker))
142                 transition-points)
143           ;; collected transitions, so build the table
144           (setq transition-points (nreverse transition-points))
145           (goto-char (pop transition-points))
146           (insert table-start doc-row-start)
147           (while (> (length transition-points) 1)
148             (goto-char (pop transition-points))
149             (insert doc-row-end code-row-start)
150             (goto-char (pop transition-points))
151             (insert code-row-end doc-row-start))
152           (goto-char (pop transition-points))
153           (insert code-row-end table-end)
154           (unless (null transition-points)
155             (error "leftover points")))))))
156 #+end_src
158 We'll use Emacs [[http://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html][File Local Variables]] and the
159 =org-export-html-final-hook= to control which buffers have
160 =org-docco-buffer= run as part of their export process.
161 #+begin_src emacs-lisp
162   (defvar org-docco-doccoize-me nil
163     "File local variable controlling if html export should be doccoized.")
164   (make-local-variable 'org-docco-doccoize-me)
165 #+end_src
167 A simple function will conditionally process HTML output based on the
168 value of this variable.
169 #+begin_src emacs-lisp
170   (defun org-docco-buffer-maybe ()
171     (when org-docco-doccoize-me (org-docco-buffer)))
172 #+end_src
174 Finally this function is added to the =org-export-html-final-hook=.
175 #+begin_src emacs-lisp
176   (add-hook 'org-export-html-final-hook #'org-docco-buffer-maybe)
177 #+end_src
179 That's it.  To use this simply;
180 1. Checkout this file from https://github.com/eschulte/org-docco,
181    : git clone git://github.com/eschulte/org-docco.git
182    and open it using Emacs.
183 2. Tangle =org-docco.el= out of this file by calling
184    =org-babel-tangle= or =C-c C-v t=.
185 3. Load the resulting Emacs Lisp file.
186 4. Execute the following in any Org-mode buffer to add file local
187    variable declarations which will enable post-processed with
188    =org-docco-buffer=.
189    : (add-file-local-variable 'org-export-html-postamble nil)
190    : (add-file-local-variable 'org-export-html-style-include-default nil)
191    : (add-file-local-variable 'org-docco-doccoize-me t)
192    And add the following style declaration to make use of the
193    =docco.css= style sheet taken directly from
194    https://github.com/jashkenas/docco.
195    : #+Style: <link rel="stylesheet" href="docco.css" type="text/css">
197 #+begin_src emacs-lisp
198 (provide 'org-docco)
199 ;;; org-docco.el ends here
200 #+end_src
202 # Local Variables:
203 # org-export-html-postamble: nil
204 # org-export-html-style-include-default: nil
205 # org-docco-doccoize-me: t
206 # End: