|
@@ -0,0 +1,186 @@
|
|
|
+;;; org-export.el --- Export engine for Org
|
|
|
+;;
|
|
|
+;; Copyright 2008 Bastien Guerry
|
|
|
+;;
|
|
|
+;; Emacs Lisp Archive Entry
|
|
|
+;; Filename: org-export.el
|
|
|
+;; Version: 0.1a
|
|
|
+;; Author: Bastien <bzg AT altern DOT org>
|
|
|
+;; Maintainer: Bastien <bzg AT altern DOT org>
|
|
|
+;; Keywords:
|
|
|
+;; Description:
|
|
|
+;; URL: [Not distributed yet]
|
|
|
+;;
|
|
|
+;; This program is free software; you can redistribute it and/or modify
|
|
|
+;; it under the terms of the GNU General Public License as published by
|
|
|
+;; the Free Software Foundation; either version 3, or (at your option)
|
|
|
+;; any later version.
|
|
|
+;;
|
|
|
+;; This program is distributed in the hope that it will be useful,
|
|
|
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+;; GNU General Public License for more details.
|
|
|
+;;
|
|
|
+;; You should have received a copy of the GNU General Public License
|
|
|
+;; along with this program; if not, write to the Free Software
|
|
|
+;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
+;;
|
|
|
+;;; Commentary:
|
|
|
+;;
|
|
|
+;; This is the export engine for Org.
|
|
|
+;;
|
|
|
+;; Put this file into your load-path and the following into your ~/.emacs:
|
|
|
+;; (require 'org-export)
|
|
|
+;;
|
|
|
+;;; Code:
|
|
|
+
|
|
|
+(eval-when-compile
|
|
|
+ (require 'cl))
|
|
|
+
|
|
|
+;;; Parsing functions:
|
|
|
+
|
|
|
+(defun org-export-parse (&optional level)
|
|
|
+ "Parse the current buffer.
|
|
|
+Return a nested list reflecting the sectioning structure of the
|
|
|
+file and containing all information about each section, including
|
|
|
+its content."
|
|
|
+ (let (output eos)
|
|
|
+ (save-excursion
|
|
|
+ (goto-char (point-min))
|
|
|
+ (while (re-search-forward org-complex-heading-regexp nil t)
|
|
|
+ (let ((heading (match-string 4))
|
|
|
+ (properties (org-entry-properties)))
|
|
|
+ (save-restriction
|
|
|
+ (narrow-to-region (if (looking-at "\n") (1+ (point)) (point))
|
|
|
+ (save-excursion
|
|
|
+ (setq eos (org-end-of-subtree t t))))
|
|
|
+ (setq output
|
|
|
+ (append output
|
|
|
+ (list
|
|
|
+ (list :level (or level 1)
|
|
|
+ :heading heading
|
|
|
+ :properties properties
|
|
|
+ :content (org-export-parse-clean-content-string
|
|
|
+ (org-export-parse-content))
|
|
|
+ :subtree (org-export-parse
|
|
|
+ (if level (1+ level) 2)))))))
|
|
|
+ (goto-char (1- eos)))))
|
|
|
+ output))
|
|
|
+
|
|
|
+(defun org-export-parse-content ()
|
|
|
+ "Extract the content of a section.
|
|
|
+The content of a section is the part before a subtree."
|
|
|
+ (save-excursion
|
|
|
+ (goto-char (point-min))
|
|
|
+ (buffer-substring
|
|
|
+ (point)
|
|
|
+ (if (re-search-forward org-complex-heading-regexp nil t)
|
|
|
+ (match-beginning 0) (point-max)))))
|
|
|
+
|
|
|
+(defun org-export-parse-clean-content-string (s)
|
|
|
+ "From the content string S, remove stuff also captured by get-properties.
|
|
|
+So this will remove the clock drawer, the property drawer, and the lines
|
|
|
+with planning info (DEADLINE, SCHEDULED, CLOSED)."
|
|
|
+ (if (string-match org-property-drawer-re s)
|
|
|
+ (setq s (replace-match "" t t s)))
|
|
|
+ (if (string-match org-clock-drawer-re s)
|
|
|
+ (setq s (replace-match "" t t s)))
|
|
|
+ (while (string-match (concat org-keyword-time-regexp ".*\n?") s)
|
|
|
+ (setq s (replace-match "" t t s)))
|
|
|
+ s)
|
|
|
+
|
|
|
+;;; Rendering functions:
|
|
|
+
|
|
|
+(defun org-export-buffer (filter struct-backend content-backend)
|
|
|
+ "Render the current buffer.
|
|
|
+It first parses the current buffer into a list. Then it filters
|
|
|
+this list with FILTER. Finally it uses STRUCT-BACKEND and
|
|
|
+CONTENT-BACKEND to render the structure of the buffer and the
|
|
|
+content of each section."
|
|
|
+ (save-excursion
|
|
|
+ (let* ((props (org-combine-plists
|
|
|
+ (org-default-export-plist)
|
|
|
+ (org-infile-export-plist)))
|
|
|
+ (first-lines (org-export-parse-content))
|
|
|
+ (parsed-buffer (org-export-parse)))
|
|
|
+ (switch-to-buffer (get-buffer-create "*Org export*"))
|
|
|
+ (erase-buffer)
|
|
|
+ (funcall (cdr (assoc 'header struct-backend)) props)
|
|
|
+ (funcall (cdr (assoc 'first-lines struct-backend))
|
|
|
+ first-lines props)
|
|
|
+ (org-export-render-structure parsed-buffer props filter
|
|
|
+ struct-backend content-backend)
|
|
|
+ (funcall (cdr (assoc 'footer struct-backend)) props))))
|
|
|
+
|
|
|
+(defun org-export-render-structure
|
|
|
+ (parsed-buffer props filter struct-backend content-backend)
|
|
|
+ "Render PARSED-BUFFER.
|
|
|
+The optional argument FILTER specifies a filter to pass to the
|
|
|
+rendering engine."
|
|
|
+ (mapc (lambda(s)
|
|
|
+ (funcall (cdr (assoc 'section-beginning struct-backend)) s)
|
|
|
+ (funcall (cdr (assoc 'heading struct-backend)) s)
|
|
|
+ (insert (org-export-render-content s props content-backend) "\n\n")
|
|
|
+ (org-export-render-structure (plist-get s :subtree) props
|
|
|
+ filter struct-backend content-backend)
|
|
|
+ (funcall (cdr (assoc 'section-end struct-backend)) s))
|
|
|
+ (org-export-filter parsed-buffer filter)))
|
|
|
+
|
|
|
+(defun org-export-render-content (section props content-backend)
|
|
|
+ "Render SECTION with PROPS. SECTION is the property list
|
|
|
+defining the information for the section. PROPS is the property
|
|
|
+list defining information for the current export.
|
|
|
+CONTENT-BACKEND is an association list defining possible
|
|
|
+exporting directive the content of this section."
|
|
|
+ (with-temp-buffer
|
|
|
+ (insert (plist-get section :content))
|
|
|
+ (if (not (plist-get props :with-comment))
|
|
|
+ (funcall (cdr (assoc 'comment content-backend))))
|
|
|
+ (buffer-string)))
|
|
|
+
|
|
|
+(defun org-export-strip-drawer ()
|
|
|
+ "Strip DRAWERS in the current buffer.
|
|
|
+Stripped drawers are those matched by `org-drawer-regexp'."
|
|
|
+ (save-excursion
|
|
|
+ (while (re-search-forward org-drawer-regexp nil t)
|
|
|
+ (let ((beg (match-beginning 0))
|
|
|
+ (end (and (search-forward ":END:" nil t)
|
|
|
+ (match-end 0))))
|
|
|
+ (delete-region beg end)))))
|
|
|
+
|
|
|
+;;; Filtering functions:
|
|
|
+
|
|
|
+(defun org-export-filter (parsed-buffer filter)
|
|
|
+ "Filter out PARSED-BUFFER with FILTER.
|
|
|
+PARSED-BUFFER is a nested list a sections and subsections, as
|
|
|
+produced by `org-export-parse'. FILTER is an alist of rules to
|
|
|
+apply to PARSED-BUFFER. For the syntax of a filter, please check
|
|
|
+the docstring of `org-export-latex-filter'."
|
|
|
+ (delete
|
|
|
+ nil
|
|
|
+ (mapcar
|
|
|
+ (lambda(s)
|
|
|
+ (if (delete
|
|
|
+ nil
|
|
|
+ (mapcar
|
|
|
+ (lambda(f)
|
|
|
+ (let ((cnd (car f)) (re (cadr f)) prop-cnd)
|
|
|
+ (or (and (eq cnd 'heading)
|
|
|
+ (string-match re (plist-get s :heading)))
|
|
|
+ (and (eq cnd 'content)
|
|
|
+ (string-match re (plist-get s :content)))
|
|
|
+ (and (setq prop-cnd
|
|
|
+ (assoc cnd (plist-get s :properties)))
|
|
|
+ (string-match re (cadr prop-cnd))))))
|
|
|
+ filter))
|
|
|
+ nil ;; return nil if the section is filtered out
|
|
|
+ (progn (plist-put s :subtree
|
|
|
+ (org-export-filter (plist-get s :subtree) filter))
|
|
|
+ s))) ;; return the section if it isn't filtered out
|
|
|
+ parsed-buffer)))
|
|
|
+
|
|
|
+(provide 'org-export)
|
|
|
+
|
|
|
+;;; User Options, Variables
|
|
|
+
|
|
|
+;;; org-export.el ends here
|