org.el: Fix bug when matching the face property before following a link.
[org-mode/org-mode-NeilSmithlineMods.git] / EXPERIMENTAL / org-export.el
blob8a79105968d4e381eddc5e3cce57701a94985348
1 ;;; org-export.el --- Export engine for Org
2 ;;
3 ;; Copyright 2008-2011 Free Software Foundation, Inc.
4 ;;
5 ;; Emacs Lisp Archive Entry
6 ;; Filename: org-export.el
7 ;; Version: 0.3
8 ;; Author: Bastien <bzg AT altern DOT org>
9 ;; Maintainer: Bastien <bzg AT altern DOT org>
10 ;; Keywords:
11 ;; Description:
12 ;; URL: [Not distributed yet]
14 ;; This file is not part of GNU Emacs.
16 ;; This program is free software; you can redistribute it and/or modify
17 ;; it under the terms of the GNU General Public License as published by
18 ;; the Free Software Foundation; either version 3, or (at your option)
19 ;; any later version.
21 ;; This program is distributed in the hope that it will be useful,
22 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 ;; GNU General Public License for more details.
26 ;; You should have received a copy of the GNU General Public License
27 ;; along with this program; if not, write to the Free Software
28 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 ;;; Commentary:
32 ;; org-export.el implements a new experimental export engine for Org.
34 ;; Put this file into your load-path and the following into your ~/.emacs:
35 ;; (require 'org-export)
37 ;;; Todo:
38 ;;
39 ;;; Code:
41 (eval-when-compile
42 (require 'cl))
44 ;;; Preparation functions:
46 ;; Currently needed for `org-export-preprocess-string'
47 (require 'org-exp)
49 (defvar org-export-structure nil)
50 (defvar org-export-content nil)
51 (defvar org-export-properties nil)
53 (defun org-export-set-backend (suffix)
54 "Set the backend functions names from SUFFIX."
55 (setq org-export-structure
56 `((header ,(intern (concat "org-" suffix "-export-header")))
57 (first-lines ,(intern (concat "org-" suffix "-export-first-lines")))
58 (section-beginning ,(intern (concat "org-" suffix "-export-section-beginning")))
59 (heading ,(intern (concat "org-" suffix "-export-heading")))
60 (section-end ,(intern (concat "org-" suffix "-export-section-end")))
61 (footer ,(intern (concat "org-" suffix "-export-footer")))))
62 (setq org-export-content
63 `((fonts ,(intern (concat "org-" suffix "-export-fonts")))
64 (links ,(intern (concat "org-" suffix "-export-links")))
65 (lists ,(intern (concat "org-" suffix "-export-lists")))
66 (envs ,(intern (concat "org-" suffix "-export-quote-verse-center")))
67 (tables ,(intern (concat "org-" suffix "-export-tables"))))))
69 ;;; Parsing functions:
71 (defun org-export-parse (&optional level)
72 "Recursively parse the current buffer.
73 If LEVEL is set, do the parsing at that level of sectioning.
74 Return a nested list containing the structure of the parsed
75 buffer and information about each section, including its
76 content."
77 (let (output eos)
78 (save-excursion
79 (goto-char (point-min))
80 (while (re-search-forward org-complex-heading-regexp nil t)
81 (let ((heading (match-string 4))
82 (properties (org-entry-properties)))
83 (save-restriction
84 (narrow-to-region (if (looking-at "\n") (1+ (point)) (point))
85 (save-excursion
86 (setq eos (org-end-of-subtree t t))))
87 (setq output
88 (append output
89 (list
90 (list :level (or level 1)
91 :heading heading
92 :properties properties
93 :content (org-export-get-entry-content)
94 :subtree (org-export-parse
95 (if level (1+ level) 2)))))))
96 (goto-char (1- eos)))))
97 output))
99 (defun org-export-get-entry-content ()
100 "Extract the content of an entry.
101 The content of a entry is the part before its first subtree or
102 the end of the entry."
103 (save-excursion
104 (goto-char (point-min))
105 ;; FIXME The following shouldn't be necessary since we are cleaning
106 ;; up the buffer ith org-export-preprocess-string
107 (while (or (looking-at org-property-drawer-re)
108 (looking-at org-clock-drawer-re)
109 (looking-at org-keyword-time-regexp))
110 (move-beginning-of-line 1))
111 (buffer-substring
112 (point)
113 (if (re-search-forward org-complex-heading-regexp nil t)
114 (match-beginning 0) (point-max)))))
116 ;;; Rendering functions:
118 (defun org-export-render (&optional filter)
119 "Render the current Org buffer and export it.
120 First parse the buffer and return it as a nested list. If FILTER
121 is set, use it to filter this list (see `org-export-filter') then
122 export the (filtered) list with `org-export-render-structure'."
123 (setq org-export-properties
124 (org-combine-plists (org-default-export-plist)
125 (org-infile-export-plist)))
126 (let* (first-lines
127 (bstring (buffer-string))
128 (parsed-buffer
129 (with-temp-buffer
130 (org-mode)
131 (insert (apply 'org-export-preprocess-string
132 bstring org-export-properties))
133 (goto-char (point-min))
134 (setq first-lines (org-export-get-entry-content))
135 (org-export-parse))))
136 (switch-to-buffer (get-buffer-create "*Org export*"))
137 (erase-buffer)
138 (funcall (cadr (assoc 'header org-export-structure)))
139 (funcall (cadr (assoc 'first-lines org-export-structure)) first-lines)
140 (org-export-render-structure parsed-buffer filter)
141 (funcall (cadr (assoc 'footer org-export-structure)))))
143 (defun org-export-render-structure (parsed-buffer &optional filter)
144 "Render PARSED-BUFFER.
145 An optional argument FILTER specifies a filter to pass to the
146 rendering engine."
147 (mapc (lambda(s)
148 (funcall (cadr (assoc 'section-beginning org-export-structure)) s)
149 (funcall (cadr (assoc 'heading org-export-structure)) s)
150 (insert (org-export-render-content s) "\n\n")
151 (org-export-render-structure (plist-get s :subtree) filter)
152 (funcall (cadr (assoc 'section-end org-export-structure)) s))
153 (org-export-filter parsed-buffer filter)))
155 (defun org-export-render-content (section)
156 "Render SECTION.
157 SECTION is either a string or a property list containing
158 informations (including content) for a section."
159 (with-temp-buffer
160 (insert (if (listp section) (plist-get section :content) section))
161 (mapc (lambda(e)
162 (goto-char (point-min))
163 (funcall (cadr (assoc e org-export-content))))
164 '(fonts tables lists envs links))
165 (buffer-string)))
167 (defun org-export-filter (parsed-buffer filter)
168 "Filter out PARSED-BUFFER with FILTER.
169 PARSED-BUFFER is a nested list of sections and subsections, as
170 produced by `org-export-parse'. FILTER is an alist of rules to
171 apply to PARSED-BUFFER. For the syntax of a filter, please check
172 the docstring of `org-export-latex-filter'."
173 ;; FIXME where is org-export-latex-filter
174 (delete
176 (mapcar
177 (lambda(s)
178 (if (delete
180 (mapcar
181 (lambda(f)
182 (let ((cnd (car f)) (re (cadr f)) prop-cnd)
183 (or (and (eq cnd 'heading)
184 (string-match re (plist-get s :heading)))
185 (and (eq cnd 'content)
186 (string-match re (plist-get s :content)))
187 (and (setq prop-cnd
188 (assoc cnd (plist-get s :properties)))
189 (string-match re (cadr prop-cnd))))))
190 filter))
191 nil ;; return nil if the section is filtered out
192 (progn (plist-put s :subtree
193 (org-export-filter (plist-get s :subtree) filter))
194 s))) ;; return the section if it isn't filtered out
195 parsed-buffer)))
197 (provide 'org-export)
199 ;;; User Options, Variables
201 ;;; org-export.el ends here