org-e-odt: Add require + autoload cookie
[org-mode.git] / contrib / lisp / org-export-generic.el
blob01a8a8c7532ffdfe3fdedec1ada7db1c7269d127
1 ;; org-export-generic.el --- Export frameworg with custom backends
3 ;; Copyright (C) 2009-2012 Free Software Foundation, Inc.
5 ;; Author: Wes Hardaker <hardaker at users dot sourceforge dot net>
6 ;; Keywords: outlines, hypermedia, calendar, wp, export
7 ;; Homepage: http://orgmode.org
8 ;; Version: 6.25trans
9 ;; Acks: Much of this code was stolen form the ascii export from Carsten
11 ;; This file is not yet part of GNU Emacs.
13 ;; GNU Emacs is free software: you can redistribute it and/or modify
14 ;; it under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation, either version 3 of the License, or
16 ;; (at your option) any later version.
18 ;; GNU Emacs is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
26 ;; ----------------------------------------------------------------------
28 ;; OVERVIEW
30 ;; org-export-generic is basically a simple translation system that
31 ;; knows how to parse at least most of a .org buffer and then add
32 ;; various formatting prefixes before and after each section type. It
33 ;; does this by examining a property list stored in org-generic-alist.
34 ;; You can dynamically add propety lists of your own using the
35 ;; org-set-generic-type function:
37 ;; (org-set-generic-type
38 ;; "really-basic-text"
39 ;; '(:file-suffix ".txt"
40 ;; :key-binding ?R
42 ;; :title-format "=== %s ===\n"
43 ;; :body-header-section-numbers t
44 ;; :body-header-section-number-format "%s) "
45 ;; :body-section-header-prefix "\n"
46 ;; :body-section-header-suffix "\n"
47 ;; :body-line-format " %s\n"
48 ;; :body-line-wrap 75
49 ;; ))
51 ;; Note: Upper case key-bindings are reserved for your use. Lower
52 ;; case key bindings may conflict with future export-generic
53 ;; publications.
55 ;; Then run org-export (ctrl-c ctrl-e) and select generic or run
56 ;; org-export-generic. You'll then be prompted with a list of export
57 ;; types to choose from which will include your new type assigned to
58 ;; the key "r".
60 ;; ----------------------------------------------------------------------
62 ;; TODO (non-ordered)
63 ;; * handle function references
64 ;; * handle other types of multi-complex-listy-things to do
65 ;; ideas: (t ?- "%s" ?-)
66 ;; * handle indent specifiers better
67 ;; ideas: (4 ?\ "%s")
68 ;; * need flag to remove indents from body text
69 ;; * handle links
70 ;; * handle internationalization strings better
71 ;; * date/author/etc needs improvment (internationalization too)
72 ;; * allow specifying of section ordering
73 ;; ideas: :ordering ("header" "toc" "body" "footer")
74 ;; ^ matches current hard coded ordering
75 ;; * err, actually *do* a footer
76 ;; * deal with usage of org globals
77 ;; *** should we even consider them, or let the per-section specifiers do it
78 ;; *** answer: remove; mostly removed now
79 ;; * deal with interactive support for picking a export specifier label
80 ;; * char specifiers that need extra length because of formatting
81 ;; idea: (?- 4) for 4-longer
82 ;; * centering specifier
83 ;; idea: ('center " -- %s -- ")
84 ;; * remove more of the unneeded export-to-ascii copy code
85 ;; * tags
86 ;; *** supported now, but need separate format per tag
87 ;; *** allow different open/closing prefixes
88 ;; * properties
89 ;; * drawers
90 ;; * Escape camel-case for wiki exporters.
91 ;; * Adjust to depth limits on headers --- need to roll-over from headers
92 ;; to lists, as per other exporters
93 ;; * optmization (many plist extracts should be in let vars)
94 ;; * define defcustom spec for the specifier list
95 ;; * fonts: at least monospace is not handled at all here.
97 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
99 ;;; Commentary:
101 (require 'org-exp)
102 (require 'assoc)
104 (defgroup org-export-generic nil
105 "Options specific for ASCII export of Org-mode files."
106 :tag "Org Export ASCII"
107 :group 'org-export)
109 (defcustom org-export-generic-links-to-notes t
110 "Non-nil means convert links to notes before the next headline.
111 When nil, the link will be exported in place. If the line becomes long
112 in this way, it will be wrapped."
113 :group 'org-export-generic
114 :type 'boolean)
117 (defvar org-generic-current-indentation nil) ; For communication
119 (defvar org-generic-alist
122 ;; generic DEMO exporter
124 ;; (this tries to use every specifier for demo purposes)
126 ("demo"
127 :file-suffix ".txt"
128 :key-binding ?d
130 :header-prefix "<header>\n"
131 :header-suffix "</header>\n"
133 :author-export t
134 :tags-export t
136 :drawers-export t
139 :title-prefix ?=
140 :title-format "<h1>%s</h1>\n"
141 :title-suffix ?=
143 :date-export t
144 :date-prefix "<date>"
145 :date-format "<br /><b>Date:</b> <i>%s</i><br />"
146 :date-suffix "</date>\n\n"
148 :toc-export t
149 :toc-header-prefix "<tocname>\n"
150 :toc-header-format "__%s__\n"
151 :toc-header-suffix "</tocname>\n"
153 :toc-prefix "<toc>\n"
154 :toc-suffix "</toc>\n"
156 :toc-section-numbers t
157 :toc-section-number-format "\#(%s) "
158 :toc-format "--%s--"
159 :toc-format-with-todo "!!%s!!\n"
160 :toc-indent-char ?\
161 :toc-indent-depth 4
163 :toc-tags-export t
164 :toc-tags-prefix " <tags>"
165 :toc-tags-format "*%s*"
166 :toc-tags-suffix "</tags>\n"
167 :toc-tags-none-string "\n"
169 :body-header-section-numbers 3 ; t = all, nil = none
171 ; lists indicate different things per level
172 ; list contents or straight value can either be a
173 ; ?x char reference for printing strings that match the header len
174 ; "" string to print directly
175 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
176 "<h4>" "<h5>" "<h6>")
177 :body-section-header-format "%s"
178 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
179 "</h4>\n" "</h5>\n" "</h6>\n")
181 :timestamps-export t
182 :priorities-export t
183 :todo-keywords-export t
185 :body-tags-export t
186 :body-tags-prefix " <tags>"
187 :body-tags-suffix "</tags>\n"
189 ; section prefixes/suffixes can be direct strings or lists as well
190 :body-section-prefix "<secprefix>\n"
191 :body-section-suffix "</secsuffix>\n"
192 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
193 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
196 ; if preformated text should be included (eg, : prefixed)
197 :body-line-export-preformated t
198 :body-line-fixed-prefix "<pre>\n"
199 :body-line-fixed-suffix "\n</pre>\n"
200 :body-line-fixed-format "%s\n"
203 :body-list-prefix "<list>\n"
204 :body-list-suffix "</list>\n"
205 :body-list-format "<li>%s</li>\n"
207 :body-number-list-prefix "<ol>\n"
208 :body-number-list-suffix "</ol>\n"
209 :body-number-list-format "<li>%s</li>\n"
210 :body-number-list-leave-number t
212 :body-list-checkbox-todo "<checkbox type=\"todo\">"
213 :body-list-checkbox-todo-end "</checkbox (todo)>"
214 :body-list-checkbox-done "<checkbox type=\"done\">"
215 :body-list-checkbox-done-end "</checkbox (done)>"
216 :body-list-checkbox-half "<checkbox type=\"half\">"
217 :body-list-checkbox-half-end "</checkbox (half)>"
222 ; other body lines
223 :body-line-format "%s"
224 :body-line-wrap 60 ; wrap at 60 chars
226 ; print above and below all body parts
227 :body-text-prefix "<p>\n"
228 :body-text-suffix "</p>\n"
233 ;; ascii exporter
235 ;; (close to the original ascii specifier)
237 ("ascii"
238 :file-suffix ".txt"
239 :key-binding ?a
241 :header-prefix ""
242 :header-suffix ""
244 :title-prefix ?=
245 :title-format "%s\n"
246 :title-suffix ?=
248 :date-export t
249 :date-prefix ""
250 :date-format "Date: %s\n"
251 :date-suffix ""
253 :toc-header-prefix ""
254 :toc-header-format "%s\n"
255 :toc-header-suffix ?=
257 :toc-export t
258 :toc-section-numbers t
259 :toc-section-number-format "%s "
260 :toc-format "%s\n"
261 :toc-format-with-todo "%s (*)\n"
262 :toc-indent-char ?\
263 :toc-indent-depth 4
265 :body-header-section-numbers 3
266 :body-section-prefix "\n"
268 ; :body-section-header-prefix "\n"
269 ; :body-section-header-format "%s\n"
270 ; :body-section-header-suffix (?\$ ?\# ?^ ?\~ ?\= ?\-)
272 :body-section-header-prefix ("" "" "" "* " " + " " - ")
273 :body-section-header-format "%s\n"
274 :body-section-header-suffix (?~ ?= ?- "\n" "\n" "\n")
276 ; :body-section-marker-prefix ""
277 ; :body-section-marker-chars (?\$ ?\# ?^ ?\~ ?\= ?\-)
278 ; :body-section-marker-suffix "\n"
280 :body-line-export-preformated t
281 :body-line-format "%s\n"
282 :body-line-wrap 75
284 ; :body-text-prefix "<t>\n"
285 ; :body-text-suffix "</t>\n"
288 :body-bullet-list-prefix (?* ?+ ?-)
289 ; :body-bullet-list-suffix (?* ?+ ?-)
293 ;; wikipedia
295 ("wikipedia"
296 :file-suffix ".txt"
297 :key-binding ?w
299 :header-prefix ""
300 :header-suffix ""
302 :title-format "= %s =\n"
304 :date-export nil
306 :toc-export nil
308 :body-header-section-numbers nil
309 :body-section-prefix "\n"
311 :body-section-header-prefix ("= " "== " "=== "
312 "==== " "===== " "====== ")
313 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
314 " ====\n\n" " =====\n\n" " ======\n\n")
316 :body-line-export-preformated t ;; yes/no/maybe???
317 :body-line-format "%s\n"
318 :body-line-wrap 75
320 :body-line-fixed-format " %s\n"
322 :body-list-format "* %s\n"
323 :body-number-list-format "# %s\n"
325 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
328 ;; mediawiki
330 ("mediawiki"
331 :file-suffix ".txt"
332 :key-binding ?m
334 :header-prefix ""
335 :header-suffix ""
337 :title-format "= %s =\n"
339 :date-export nil
341 :toc-export nil
343 :body-header-section-numbers nil
344 :body-section-prefix "\n"
346 :body-section-header-prefix ("= " "== " "=== "
347 "==== " "===== " "====== ")
348 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
349 " ====\n\n" " =====\n\n" " ======\n\n")
351 :body-line-export-preformated t ;; yes/no/maybe???
352 :body-line-format "%s\n"
353 :body-line-wrap 75
355 :body-line-fixed-format " %s\n"
357 :body-list-format "* %s\n"
358 :body-number-list-format "# %s\n"
360 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
361 :body-list-checkbox-todo "&#9744; "
362 :body-list-checkbox-done "&#9746; "
363 :body-table-start "{|"
364 :body-table-end "|}"
365 :body-table-cell-start "|"
366 :body-table-cell-end "\n"
367 :body-table-last-cell-end "|-"
368 :body-table-hline-start ""
373 ;; internet-draft .xml for xml2rfc exporter
375 ("ietfid"
376 ;; this tries to use every specifier for demo purposes
377 :file-suffix ".xml"
378 :key-binding ?i
380 :title-prefix "<?xml version=\"1.0\"\?>
381 <!DOCTYPE rfc SYSTEM \"rfc2629.dtd\" [
382 <!ENTITY rfcs PUBLIC '' 'blah'>
383 <?rfc strict=\"yes\" ?>
384 <?rfc toc=\"yes\" ?>
385 <?rfc tocdepth=\"4\" ?>
386 <?rfc symrefs=\"yes\" ?>
387 <?rfc compact=\"yes\" ?>
388 <?rfc subcompact=\"no\" ?>
389 <rfc category=\"std\" ipr=\"pre5378Trust200902\" docName=\"FILLME.txt\">
390 <front>
392 :title-format "<title abbrev=\"ABBREV HERE\">\n%s\n</title>\n"
393 :title-suffix "<author initials=\"A.A\" surname=\"LASTNAME\" fullname=\"FULL NAME\">
394 <organization>Comany, Inc..</organization>
395 <address>
396 <postal>
397 <street></street>
398 <city></city>
399 <region></region>
400 <code></code>
401 <country></country>
402 </postal>
403 <phone></phone>
404 <email></email>
405 </address>
406 </author>
407 <date month=\"FILLMONTH\" year=\"FILLYEAR\"/>
408 <area>Operations and Management</area>
409 <workgroup>FIXME</workgroup>
410 <abstract>\n"
411 :date-export nil
413 :toc-export nil
415 :body-header-section-numbers nil
417 :body-section-header-format "<section title=\"%s\">\n"
418 :body-section-suffix "</section>\n"
420 ; if preformated text should be included (eg, : prefixed)
421 :body-line-export-preformated t
422 :body-line-fixed-prefix "<figure>\n<artwork>\n"
423 :body-line-fixed-suffix "\n</artwork>\n</figure>\n"
425 ; other body lines
426 :body-line-format "%s"
427 :body-line-wrap 75
429 ; print above and below all body parts
430 :body-text-prefix "<t>\n"
431 :body-text-suffix "</t>\n"
433 :body-list-prefix "<list style=\"symbols\">\n"
434 :body-list-suffix "</list>\n"
435 :body-list-format "<t>%s</t>\n"
438 ("trac-wiki"
439 :file-suffix ".txt"
440 :key-binding ?T
442 ;; lifted from wikipedia exporter
443 :header-prefix ""
444 :header-suffix ""
446 :title-format "= %s =\n"
448 :date-export nil
450 :toc-export nil
452 :body-header-section-numbers nil
453 :body-section-prefix "\n"
455 :body-section-header-prefix (" == " " === " " ==== "
456 " ===== " )
457 :body-section-header-suffix (" ==\n\n" " ===\n\n" " ====\n\n"
458 " =====\n\n" " ======\n\n" " =======\n\n")
460 :body-line-export-preformated t ;; yes/no/maybe???
461 :body-line-format "%s\n"
462 :body-line-wrap 75
464 :body-line-fixed-format " %s\n"
466 :body-list-format " * %s\n"
467 :body-number-list-format " # %s\n"
468 ;; :body-list-prefix "LISTSTART"
469 ;; :body-list-suffix "LISTEND"
471 ;; this is ignored! [2010/02/02:rpg]
472 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
474 ("tikiwiki"
475 :file-suffix ".txt"
476 :key-binding ?U
478 ;; lifted from wikipedia exporter
479 :header-prefix ""
480 :header-suffix ""
482 :title-format "-= %s =-\n"
484 :date-export nil
486 :toc-export nil
488 :body-header-section-numbers nil
489 :body-section-prefix "\n"
491 :body-section-header-prefix ("! " "!! " "!!! " "!!!! "
492 "!!!!! " "!!!!!! " "!!!!!!! ")
493 :body-section-header-suffix (" \n" " \n" " \n"
494 " \n" " \n" " \n")
497 :body-line-export-preformated t ;; yes/no/maybe???
498 :body-line-format "%s "
499 :body-line-wrap nil
501 :body-line-fixed-format " %s\n"
503 :body-list-format "* %s\n"
504 :body-number-list-format "# %s\n"
505 ;; :body-list-prefix "LISTSTART"
506 ;; :body-list-suffix "LISTEND"
507 :blockquote-start "\n^\n"
508 :blockquote-end "^\n\n"
509 :body-newline-paragraph "\n"
510 :bold-format "__%s__"
511 :italic-format "''%s''"
512 :underline-format "===%s==="
513 :strikethrough-format "--%s--"
514 :code-format "-+%s+-"
515 :verbatim-format "~pp~%s~/pp~"
518 "A assoc list of property lists to specify export definitions"
521 (setq org-generic-export-type "demo")
523 (defvar org-export-generic-section-type "")
524 (defvar org-export-generic-section-suffix "")
526 ;;;###autoload
527 (defun org-set-generic-type (type definition)
528 "Adds a TYPE and DEFINITION to the existing list of defined generic
529 export definitions."
530 (aput 'org-generic-alist type definition))
532 ;;; helper functions for org-set-generic-type
533 (defvar org-export-generic-keywords nil)
534 (defmacro* def-org-export-generic-keyword (keyword
535 &key documentation
536 type)
537 "Define KEYWORD as a legitimate element for inclusion in
538 the body of an org-set-generic-type definition."
539 `(progn
540 (pushnew ,keyword org-export-generic-keywords)
541 ;; TODO: push the documentation and type information
542 ;; somewhere where it will do us some good.
545 (def-org-export-generic-keyword :body-newline-paragraph
546 :documentation "Bound either to NIL or to a pattern to be
547 inserted in the output for every blank line in the input.
548 The intention is to handle formats where text is flowed, and
549 newlines are interpreted as significant \(e.g., as indicating
550 preformatted text\). A common non-nil value for this keyword
551 is \"\\n\". Should typically be combined with a value for
552 :body-line-format that does NOT end with a newline."
553 :type string)
555 ;;; fontification keywords
556 (def-org-export-generic-keyword :bold-format)
557 (def-org-export-generic-keyword :italic-format)
558 (def-org-export-generic-keyword :underline-format)
559 (def-org-export-generic-keyword :strikethrough-format)
560 (def-org-export-generic-keyword :code-format)
561 (def-org-export-generic-keyword :verbatim-format)
566 (defun org-export-generic-remember-section (type suffix &optional prefix)
567 (setq org-export-generic-section-type type)
568 (setq org-export-generic-section-suffix suffix)
569 (if prefix
570 (insert prefix))
573 (defun org-export-generic-check-section (type &optional prefix suffix)
574 "checks to see if type is already in use, or we're switching parts
575 If we're switching, then insert a potentially previously remembered
576 suffix, and insert the current prefix immediately and then save the
577 suffix a later change time."
579 (when (not (equal type org-export-generic-section-type))
580 (if org-export-generic-section-suffix
581 (insert org-export-generic-section-suffix))
582 (setq org-export-generic-section-type type)
583 (setq org-export-generic-section-suffix suffix)
584 (if prefix
585 (insert prefix))))
587 ;;;###autoload
588 (defun org-export-generic (arg)
589 "Export the outline as generic output.
590 If there is an active region, export only the region.
591 The prefix ARG specifies how many levels of the outline should become
592 underlined headlines. The default is 3."
593 (interactive "P")
594 (setq-default org-todo-line-regexp org-todo-line-regexp)
595 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
596 (org-infile-export-plist)))
597 (region-p (org-region-active-p))
598 (rbeg (and region-p (region-beginning)))
599 (rend (and region-p (region-end)))
600 (subtree-p
601 (when region-p
602 (save-excursion
603 (goto-char rbeg)
604 (and (org-at-heading-p)
605 (>= (org-end-of-subtree t t) rend)))))
606 (level-offset (if subtree-p
607 (save-excursion
608 (goto-char rbeg)
609 (+ (funcall outline-level)
610 (if org-odd-levels-only 1 0)))
612 (opt-plist (setq org-export-opt-plist
613 (if subtree-p
614 (org-export-add-subtree-options opt-plist rbeg)
615 opt-plist)))
617 helpstart
618 (bogus (mapc (lambda (x)
619 (setq helpstart
620 (concat helpstart "\["
621 (char-to-string
622 (plist-get (cdr x) :key-binding))
623 "] " (car x) "\n")))
624 org-generic-alist))
626 (help (concat helpstart "
628 \[ ] the current setting of the org-generic-export-type variable
631 (cmds
633 (append
634 (mapcar (lambda (x)
635 (list
636 (plist-get (cdr x) :key-binding)
637 (car x)))
638 org-generic-alist)
639 (list (list ? "default"))))
641 r1 r2 ass
643 ;; read in the type to use
644 (export-plist
645 (progn
646 (save-excursion
647 (save-window-excursion
648 (delete-other-windows)
649 (with-output-to-temp-buffer "*Org Export/Generic Styles Help*"
650 (princ help))
651 (org-fit-window-to-buffer (get-buffer-window
652 "*Org Export/Generic Styles Help*"))
653 (message "Select command: ")
654 (setq r1 (read-char-exclusive))))
655 (setq r2 (if (< r1 27) (+ r1 96) r1))
656 (unless (setq ass (cadr (assq r2 cmds)))
657 (error "No command associated with key %c" r1))
659 (cdr (assoc
660 (if (equal ass "default") org-generic-export-type ass)
661 org-generic-alist))))
663 (custom-times org-display-custom-times)
664 (org-generic-current-indentation '(0 . 0))
665 (level 0) (old-level 0) line txt lastwastext
666 (umax nil)
667 (umax-toc nil)
668 (case-fold-search nil)
669 (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
670 (filesuffix (or (plist-get export-plist :file-suffix) ".foo"))
671 (filename (concat (file-name-as-directory
672 (org-export-directory :ascii opt-plist))
673 (file-name-sans-extension
674 (or (and subtree-p
675 (org-entry-get (region-beginning)
676 "EXPORT_FILE_NAME" t))
677 (file-name-nondirectory bfname)))
678 filesuffix))
679 (filename (if (equal (file-truename filename)
680 (file-truename bfname))
681 (concat filename filesuffix)
682 filename))
683 (buffer (find-file-noselect filename))
684 (org-levels-open (make-vector org-level-max nil))
685 (odd org-odd-levels-only)
686 (date (plist-get opt-plist :date))
687 (author (plist-get opt-plist :author))
688 (title (or (and subtree-p (org-export-get-title-from-subtree))
689 (plist-get opt-plist :title)
690 (and (not
691 (plist-get opt-plist :skip-before-1st-heading))
692 (org-export-grab-title-from-buffer))
693 (file-name-sans-extension
694 (file-name-nondirectory bfname))))
695 (email (plist-get opt-plist :email))
696 (language (plist-get opt-plist :language))
697 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
698 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
699 (todo nil)
700 (lang-words nil)
701 (region
702 (buffer-substring
703 (if (org-region-active-p) (region-beginning) (point-min))
704 (if (org-region-active-p) (region-end) (point-max))))
705 (org-export-current-backend 'org-export-generic)
706 (lines (org-split-string
707 (org-export-preprocess-string
708 region
709 :for-backend 'ascii
710 :skip-before-1st-heading
711 (plist-get opt-plist :skip-before-1st-heading)
712 :drawers (plist-get export-plist :drawers-export)
713 :tags (plist-get export-plist :tags-export)
714 :priority (plist-get export-plist :priority-export)
715 :footnotes (plist-get export-plist :footnotes-export)
716 :timestamps (plist-get export-plist :timestamps-export)
717 :todo-keywords (plist-get export-plist :todo-keywords-export)
718 :verbatim-multiline t
719 :select-tags (plist-get export-plist :select-tags-export)
720 :exclude-tags (plist-get export-plist :exclude-tags-export)
721 :emph-multiline t
722 :archived-trees
723 (plist-get export-plist :archived-trees-export)
724 :add-text (plist-get opt-plist :text))
725 "\n"))
726 ;; export-generic plist variables
727 (withtags (plist-get export-plist :tags-export))
728 (tagsintoc (plist-get export-plist :toc-tags-export))
729 (tocnotagsstr (or (plist-get export-plist :toc-tags-none-string) ""))
730 (tocdepth (plist-get export-plist :toc-indent-depth))
731 (tocindentchar (plist-get export-plist :toc-indent-char))
732 (tocsecnums (plist-get export-plist :toc-section-numbers))
733 (tocsecnumform (plist-get export-plist :toc-section-number-format))
734 (tocformat (plist-get export-plist :toc-format))
735 (tocformtodo (plist-get export-plist :toc-format-with-todo))
736 (tocprefix (plist-get export-plist :toc-prefix))
737 (tocsuffix (plist-get export-plist :toc-suffix))
738 (bodyfixedpre (plist-get export-plist :body-line-fixed-prefix))
739 (bodyfixedsuf (plist-get export-plist :body-line-fixed-suffix))
740 (bodyfixedform (or (plist-get export-plist :body-line-fixed-format)
741 "%s"))
742 (listprefix (plist-get export-plist :body-list-prefix))
743 (listsuffix (plist-get export-plist :body-list-suffix))
744 (listformat (or (plist-get export-plist :body-list-format) "%s\n"))
745 (numlistleavenum
746 (plist-get export-plist :body-number-list-leave-number))
747 (numlistprefix (plist-get export-plist :body-number-list-prefix))
748 (numlistsuffix (plist-get export-plist :body-number-list-suffix))
749 (numlistformat
750 (or (plist-get export-plist :body-number-list-format) "%s\n"))
751 (listchecktodo
752 (or (plist-get export-plist :body-list-checkbox-todo) "\\1"))
753 (listcheckdone
754 (or (plist-get export-plist :body-list-checkbox-done) "\\1"))
755 (listcheckhalf
756 (or (plist-get export-plist :body-list-checkbox-half) "\\1"))
757 (listchecktodoend
758 (or (plist-get export-plist :body-list-checkbox-todo-end) ""))
759 (listcheckdoneend
760 (or (plist-get export-plist :body-list-checkbox-done-end) ""))
761 (listcheckhalfend
762 (or (plist-get export-plist :body-list-checkbox-half-end) ""))
763 (bodytablestart
764 (or (plist-get export-plist :body-table-start) ""))
765 (bodytableend
766 (or (plist-get export-plist :body-table-end) ""))
767 (bodytablerowstart
768 (or (plist-get export-plist :body-table-row-start) ""))
769 (bodytablerowend
770 (or (plist-get export-plist :body-table-row-end) ""))
771 (bodytablecellstart
772 (or (plist-get export-plist :body-table-cell-start) ""))
773 (bodytablecellend
774 (or (plist-get export-plist :body-table-cell-end) ""))
775 (bodytablefirstcellstart
776 (or (plist-get export-plist :body-table-first-cell-start) ""))
777 (bodytableinteriorcellstart
778 (or (plist-get export-plist :body-table-interior-cell-start) ""))
779 (bodytableinteriorcellend
780 (or (plist-get export-plist :body-table-interior-cell-end) ""))
781 (bodytablelastcellend
782 (or (plist-get export-plist :body-table-last-cell-end) ""))
783 (bodytablehlinestart
784 (or (plist-get export-plist :body-table-hline-start) " \\1"))
785 (bodytablehlineend
786 (or (plist-get export-plist :body-table-hline-end) ""))
790 (bodynewline-paragraph (plist-get export-plist :body-newline-paragraph))
791 (bodytextpre (plist-get export-plist :body-text-prefix))
792 (bodytextsuf (plist-get export-plist :body-text-suffix))
793 (bodylinewrap (plist-get export-plist :body-line-wrap))
794 (bodylineform (or (plist-get export-plist :body-line-format) "%s"))
795 (blockquotestart (or (plist-get export-plist :blockquote-start) "\n\n\t"))
796 (blockquoteend (or (plist-get export-plist :blockquote-end) "\n\n"))
798 ;; dynamic variables used heinously in fontification
799 ;; not referenced locally...
800 (format-boldify (plist-get export-plist :bold-format))
801 (format-italicize (plist-get export-plist :italic-format))
802 (format-underline (plist-get export-plist :underline-format))
803 (format-strikethrough (plist-get export-plist :strikethrough-format))
804 (format-code (plist-get export-plist :code-format))
805 (format-verbatim (plist-get export-plist :verbatim-format))
809 thetoc toctags have-headings first-heading-pos
810 table-open table-buffer link-buffer link desc desc0 rpl wrap)
812 (let ((inhibit-read-only t))
813 (org-unmodified
814 (remove-text-properties (point-min) (point-max)
815 '(:org-license-to-kill t))))
817 (setq org-min-level (org-get-min-level lines level-offset))
818 (setq org-last-level org-min-level)
819 (org-init-section-numbers)
821 (find-file-noselect filename)
823 (setq lang-words (or (assoc language org-export-language-setup)
824 (assoc "en" org-export-language-setup)))
825 (switch-to-buffer-other-window buffer)
826 (erase-buffer)
827 (fundamental-mode)
828 ;; create local variables for all options, to make sure all called
829 ;; functions get the correct information
830 (mapc (lambda (x)
831 (set (make-local-variable (nth 2 x))
832 (plist-get opt-plist (car x))))
833 org-export-plist-vars)
834 (org-set-local 'org-odd-levels-only odd)
835 (setq umax (if arg (prefix-numeric-value arg)
836 org-export-headline-levels))
837 (setq umax-toc umax)
839 ;; File header
840 (if title
841 (insert
842 (org-export-generic-header title export-plist
843 :title-prefix
844 :title-format
845 :title-suffix)))
847 (if (and (or author email)
848 (plist-get export-plist :author-export))
849 (insert (concat (nth 1 lang-words) ": " (or author "")
850 (if email (concat " <" email ">") "")
851 "\n")))
853 (cond
854 ((and date (string-match "%" date))
855 (setq date (format-time-string date)))
856 (date)
857 (t (setq date (format-time-string "%Y-%m-%d %T %Z"))))
859 (if (and date (plist-get export-plist :date-export))
860 (insert
861 (org-export-generic-header date export-plist
862 :date-prefix
863 :date-format
864 :date-suffix)))
866 ;; export the table of contents first
867 (if (plist-get export-plist :toc-export)
868 (progn
869 (push
870 (org-export-generic-header (nth 3 lang-words) export-plist
871 :toc-header-prefix
872 :toc-header-format
873 :toc-header-suffix)
874 thetoc)
876 (if tocprefix
877 (push tocprefix thetoc))
879 (mapc '(lambda (line)
880 (if (string-match org-todo-line-regexp line)
881 ;; This is a headline
882 (progn
883 (setq have-headings t)
884 (setq level (- (match-end 1) (match-beginning 1)
885 level-offset)
886 level (org-tr-level level)
887 txt (match-string 3 line)
888 todo
889 (or (and org-export-mark-todo-in-toc
890 (match-beginning 2)
891 (not (member (match-string 2 line)
892 org-done-keywords)))
893 ; TODO, not DONE
894 (and org-export-mark-todo-in-toc
895 (= level umax-toc)
896 (org-search-todo-below
897 line lines level))))
898 (setq txt (org-html-expand-for-generic txt))
900 (while (string-match org-bracket-link-regexp txt)
901 (setq txt
902 (replace-match
903 (match-string (if (match-end 2) 3 1) txt)
904 t t txt)))
906 (if (and (not tagsintoc)
907 (string-match
908 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
909 txt))
910 (setq txt (replace-match "" t t txt))
911 ; include tags but formated
912 (if (string-match
913 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$")
914 txt)
915 (progn
916 (setq
917 toctags
918 (org-export-generic-header
919 (match-string 1 txt)
920 export-plist :toc-tags-prefix
921 :toc-tags-format :toc-tags-suffix))
922 (string-match
923 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
924 txt)
925 (setq txt (replace-match "" t t txt)))
926 (setq toctags tocnotagsstr)))
928 (if (string-match quote-re0 txt)
929 (setq txt (replace-match "" t t txt)))
931 (if (<= level umax-toc)
932 (progn
933 (push
934 (concat
936 (make-string
937 (* (max 0 (- level org-min-level)) tocdepth)
938 tocindentchar)
940 (if tocsecnums
941 (format tocsecnumform
942 (org-section-number level))
945 (format
946 (if todo tocformtodo tocformat)
947 txt)
949 toctags)
951 thetoc)
952 (setq org-last-level level))
953 ))))
954 lines)
955 (if tocsuffix
956 (push tocsuffix thetoc))
957 (setq thetoc (if have-headings (nreverse thetoc) nil))))
959 (org-init-section-numbers)
960 (org-export-generic-check-section "top")
961 (while (setq line (pop lines))
962 (when (and link-buffer (string-match org-outline-regexp-bol line))
963 (org-export-generic-push-links (nreverse link-buffer))
964 (setq link-buffer nil))
965 (setq wrap nil)
966 ;; Remove the quoted HTML tags.
967 ;; XXX
968 (setq line (org-html-expand-for-generic line))
969 ;; Replace links with the description when possible
970 ;; XXX
971 (while (string-match org-bracket-link-regexp line)
972 (setq link (match-string 1 line)
973 desc0 (match-string 3 line)
974 desc (or desc0 (match-string 1 line)))
975 (if (and (> (length link) 8)
976 (equal (substring link 0 8) "coderef:"))
977 (setq line (replace-match
978 (format (org-export-get-coderef-format (substring link 8) desc)
979 (cdr (assoc
980 (substring link 8)
981 org-export-code-refs)))
982 t t line))
983 (setq rpl (concat "["
984 (or (match-string 3 line) (match-string 1 line))
985 "]"))
986 (when (and desc0 (not (equal desc0 link)))
987 (if org-export-generic-links-to-notes
988 (push (cons desc0 link) link-buffer)
989 (setq rpl (concat rpl " (" link ")")
990 wrap (+ (length line) (- (length (match-string 0 line)))
991 (length desc)))))
992 (setq line (replace-match rpl t t line))))
993 (when custom-times
994 (setq line (org-translate-time line)))
995 (cond
996 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
998 ;; a Headline
1000 (org-export-generic-check-section "headline")
1002 (setq first-heading-pos (or first-heading-pos (point)))
1003 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)
1004 level-offset))
1005 txt (match-string 2 line))
1006 (org-generic-level-start level old-level txt umax export-plist lines)
1007 (setq old-level level))
1009 ((and org-export-with-tables
1010 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
1012 ;; a Table
1014 (org-export-generic-check-section "table")
1016 (if (not table-open)
1017 ;; New table starts
1018 (setq table-open t table-buffer nil))
1019 ;; Accumulate table lines
1020 (setq table-buffer (cons line table-buffer))
1021 (when (or (not lines)
1022 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
1023 (car lines))))
1024 (setq table-open nil
1025 table-buffer (nreverse table-buffer))
1026 (insert (mapconcat
1027 (lambda (x)
1028 (org-fix-indentation x org-generic-current-indentation))
1029 (org-format-table-generic table-buffer)
1030 "\n") "\n")))
1032 ((string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)
1034 ;; pre-formatted text
1036 (setq line (replace-match "\\1" nil nil line))
1038 (org-export-generic-check-section "preformat" bodyfixedpre bodyfixedsuf)
1040 (insert (format bodyfixedform line)))
1042 ((or (string-match "^\\([ \t]*\\)\\([\-\+][ \t]*\\)" line)
1043 ;; if the bullet list item is an asterisk, the leading space is /mandatory/
1044 ;; [2010/02/02:rpg]
1045 (string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
1047 ;; plain list item
1048 ;; TODO: nested lists
1050 ;; first add a line break between any previous paragraph or line item and this
1051 ;; one
1052 (when bodynewline-paragraph
1053 (insert bodynewline-paragraph))
1055 ;; I believe this gets rid of leading whitespace.
1056 (setq line (replace-match "" nil nil line))
1058 ;; won't this insert the suffix /before/ the last line of the list?
1059 ;; also isn't it spoofed by bulleted lists that have a line skip between the list items
1060 ;; unless 'org-empty-line-terminates-plain-lists' is true?
1061 (org-export-generic-check-section "liststart" listprefix listsuffix)
1063 ;; deal with checkboxes
1064 (cond
1065 ((string-match "^\\(\\[ \\]\\)[ \t]*" line)
1066 (setq line (concat (replace-match listchecktodo nil nil line)
1067 listchecktodoend)))
1068 ((string-match "^\\(\\[X\\]\\)[ \t]*" line)
1069 (setq line (concat (replace-match listcheckdone nil nil line)
1070 listcheckdoneend)))
1071 ((string-match "^\\(\\[/\\]\\)[ \t]*" line)
1072 (setq line (concat (replace-match listcheckhalf nil nil line)
1073 listcheckhalfend)))
1076 (insert (format listformat (org-export-generic-fontify line))))
1077 ((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
1079 ;; numbered list item
1081 ;; TODO: nested lists
1083 (setq line (replace-match (if numlistleavenum "\\2" "") nil nil line))
1085 (org-export-generic-check-section "numliststart"
1086 numlistprefix numlistsuffix)
1088 ;; deal with checkboxes
1089 ;; TODO: whoops; leaving the numbers is a problem for ^ matching
1090 (cond
1091 ((string-match "\\(\\[ \\]\\)[ \t]*" line)
1092 (setq line (concat (replace-match listchecktodo nil nil line)
1093 listchecktodoend)))
1094 ((string-match "\\(\\[X\\]\\)[ \t]*" line)
1095 (setq line (concat (replace-match listcheckdone nil nil line)
1096 listcheckdoneend)))
1097 ((string-match "\\(\\[/\\]\\)[ \t]*" line)
1098 (setq line (concat (replace-match listcheckhalf nil nil line)
1099 listcheckhalfend)))
1102 (insert (format numlistformat (org-export-generic-fontify line))))
1104 ((equal line "ORG-BLOCKQUOTE-START")
1105 (setq line blockquotestart))
1106 ((equal line "ORG-BLOCKQUOTE-END")
1107 (setq line blockquoteend))
1108 ((string-match "^\\s-*$" line)
1109 ;; blank line
1110 (if bodynewline-paragraph
1111 (insert bodynewline-paragraph)))
1114 ;; body
1116 (org-export-generic-check-section "body" bodytextpre bodytextsuf)
1118 (setq line
1119 (org-export-generic-fontify line))
1121 ;; XXX: properties? list?
1122 (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
1123 (setq line (replace-match "\\1\\3:" t nil line)))
1125 (setq line (org-fix-indentation line org-generic-current-indentation))
1127 ;; Remove forced line breaks
1128 (if (string-match "\\\\\\\\[ \t]*$" line)
1129 (setq line (replace-match "" t t line)))
1131 (if bodylinewrap
1132 ;; XXX: was dependent on wrap var which was calculated by???
1133 (if (> (length line) bodylinewrap)
1134 (setq line
1135 (org-export-generic-wrap line bodylinewrap))
1136 (setq line line)))
1137 (insert (format bodylineform line)))))
1139 ;; if we're at a level > 0; insert the closing body level stuff
1140 (let ((counter 0))
1141 (while (> (- level counter) 0)
1142 (insert
1143 (org-export-generic-format export-plist :body-section-suffix 0
1144 (- level counter)))
1145 (setq counter (1+ counter))))
1147 (org-export-generic-check-section "bottom")
1149 (org-export-generic-push-links (nreverse link-buffer))
1151 (normal-mode)
1153 ;; insert the table of contents
1154 (when thetoc
1155 (goto-char (point-min))
1156 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
1157 (progn
1158 (goto-char (match-beginning 0))
1159 (replace-match ""))
1160 (goto-char first-heading-pos))
1161 (mapc 'insert thetoc)
1162 (or (looking-at "[ \t]*\n[ \t]*\n")
1163 (insert "\n\n")))
1165 ;; Convert whitespace place holders
1166 (goto-char (point-min))
1167 (let (beg end)
1168 (while (setq beg (next-single-property-change (point) 'org-whitespace))
1169 (setq end (next-single-property-change beg 'org-whitespace))
1170 (goto-char beg)
1171 (delete-region beg end)
1172 (insert (make-string (- end beg) ?\ ))))
1174 (save-buffer)
1176 ;; remove display and invisible chars
1177 (let (beg end)
1178 (goto-char (point-min))
1179 (while (setq beg (next-single-property-change (point) 'display))
1180 (setq end (next-single-property-change beg 'display))
1181 (delete-region beg end)
1182 (goto-char beg)
1183 (insert "=>"))
1184 (goto-char (point-min))
1185 (while (setq beg (next-single-property-change (point) 'org-cwidth))
1186 (setq end (next-single-property-change beg 'org-cwidth))
1187 (delete-region beg end)
1188 (goto-char beg)))
1189 (goto-char (point-min))))
1192 (defun org-export-generic-format (export-plist prop &optional len n reverse)
1193 "converts a property specification to a string given types of properties
1195 The EXPORT-PLIST should be defined as the lookup plist.
1196 The PROP should be the property name to search for in it.
1197 LEN is set to the length of multi-characters strings to generate (or 0)
1198 N is the tree depth
1199 REVERSE means to reverse the list if the plist match is a list
1201 (let* ((prefixtype (plist-get export-plist prop))
1202 subtype)
1203 (cond
1204 ((null prefixtype) "")
1205 ((and len (char-or-string-p prefixtype) (not (stringp prefixtype)))
1206 ;; sequence of chars
1207 (concat (make-string len prefixtype) "\n"))
1208 ((stringp prefixtype)
1209 prefixtype)
1210 ((and n (listp prefixtype))
1211 (if reverse
1212 (setq prefixtype (reverse prefixtype)))
1213 (setq subtype (if (> n (length prefixtype))
1214 (car (last prefixtype))
1215 (nth (1- n) prefixtype)))
1216 (if (stringp subtype)
1217 subtype
1218 (concat (make-string len subtype) "\n")))
1219 (t ""))
1222 (defun org-export-generic-header (header export-plist
1223 prefixprop formatprop postfixprop
1224 &optional n reverse)
1225 "convert a header to an output string given formatting property names"
1226 (let* ((formatspec (plist-get export-plist formatprop))
1227 (len (length header)))
1228 (concat
1229 (org-export-generic-format export-plist prefixprop len n reverse)
1230 (format (or formatspec "%s") header)
1231 (org-export-generic-format export-plist postfixprop len n reverse))
1234 (defun org-export-generic-preprocess (parameters)
1235 "Do extra work for ASCII export"
1236 ;; Put quotes around verbatim text
1237 (goto-char (point-min))
1238 (while (re-search-forward org-verbatim-re nil t)
1239 (goto-char (match-end 2))
1240 (backward-delete-char 1) (insert "'")
1241 (goto-char (match-beginning 2))
1242 (delete-char 1) (insert "`")
1243 (goto-char (match-end 2)))
1244 ;; Remove target markers
1245 (goto-char (point-min))
1246 (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t)
1247 (replace-match "\\1\\2")))
1249 (defun org-html-expand-for-generic (line)
1250 "Handle quoted HTML for ASCII export."
1251 (if org-export-html-expand
1252 (while (string-match "@<[^<>\n]*>" line)
1253 ;; We just remove the tags for now.
1254 (setq line (replace-match "" nil nil line))))
1255 line)
1257 (defun org-export-generic-wrap (line where)
1258 "Wrap LINE at or before WHERE."
1259 (let* ((ind (org-get-indentation line))
1260 (indstr (make-string ind ?\ ))
1261 (len (length line))
1262 (result "")
1263 pos didfirst)
1264 (while (> len where)
1265 (catch 'found
1266 (loop for i from where downto (/ where 2) do
1267 (and (equal (aref line i) ?\ )
1268 (setq pos i)
1269 (throw 'found t))))
1270 (if pos
1271 (progn
1272 (setq result
1273 (concat result
1274 (if didfirst indstr "")
1275 (substring line 0 pos)
1276 "\n"))
1277 (setq didfirst t)
1278 (setq line (substring line (1+ pos)))
1279 (setq len (length line)))
1280 (setq result (concat result line))
1281 (setq len 0)))
1282 (concat result indstr line)))
1284 (defun org-export-generic-push-links (link-buffer)
1285 "Push out links in the buffer."
1286 (when link-buffer
1287 ;; We still have links to push out.
1288 (insert "\n")
1289 (let ((ind ""))
1290 (save-match-data
1291 (if (save-excursion
1292 (re-search-backward
1293 "^\\(\\([ \t]*\\)\\|\\(\\*+ \\)\\)[^ \t\n]" nil t))
1294 (setq ind (or (match-string 2)
1295 (make-string (length (match-string 3)) ?\ )))))
1296 (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n"))
1297 link-buffer))
1298 (insert "\n")))
1300 (defun org-generic-level-start (level old-level title umax export-plist
1301 &optional lines)
1302 "Insert a new level in a generic export."
1303 (let ((n (- level umax 1))
1304 (ind 0)
1305 (diff (- level old-level)) (counter 0)
1306 (secnums (plist-get export-plist :body-header-section-numbers))
1307 (secnumformat
1308 (plist-get export-plist :body-header-section-number-format))
1309 char tagstring)
1310 (unless org-export-with-tags
1311 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
1312 (setq title (replace-match "" t t title))))
1314 (cond
1315 ;; going deeper
1316 ((> level old-level)
1317 (while (< (+ old-level counter) (1- level))
1318 (insert
1319 (org-export-generic-format export-plist :body-section-prefix 0
1320 (+ old-level counter)))
1321 (setq counter (1+ counter))
1323 ;; going up
1324 ((< level old-level)
1325 (while (> (- old-level counter) (1- level))
1326 (insert
1327 (org-export-generic-format export-plist :body-section-suffix 0
1328 (- old-level counter)))
1329 (setq counter (1+ counter))
1331 ;; same level
1332 ((= level old-level)
1333 (insert
1334 (org-export-generic-format export-plist :body-section-suffix 0 level))
1337 (insert
1338 (org-export-generic-format export-plist :body-section-prefix 0 level))
1340 (if (and org-export-with-section-numbers
1341 secnums
1342 (or (not (numberp secnums))
1343 (< level secnums)))
1344 (setq title
1345 (concat (format (or secnumformat "%s ")
1346 (org-section-number level)) title)))
1348 ;; handle tags and formatting
1349 (if (string-match
1350 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") title)
1351 (progn
1352 (if (plist-get export-plist :body-tags-export)
1353 (setq tagstring (org-export-generic-header (match-string 1 title)
1354 export-plist
1355 :body-tags-prefix
1356 :body-tags-format
1357 :body-tags-suffix)))
1358 (string-match (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$") title)
1359 (setq title (replace-match "" t t title)))
1360 (setq tagstring (plist-get export-plist :body-tags-none-string)))
1362 (insert
1363 (org-export-generic-header title export-plist
1364 :body-section-header-prefix
1365 :body-section-header-format
1366 :body-section-header-suffix
1367 level))
1368 (if tagstring
1369 (insert tagstring))
1371 (setq org-generic-current-indentation '(0 . 0))))
1373 (defun org-insert-centered (s &optional underline)
1374 "Insert the string S centered and underline it with character UNDERLINE."
1375 (let ((ind (max (/ (- fill-column (string-width s)) 2) 0)))
1376 (insert (make-string ind ?\ ) s "\n")
1377 (if underline
1378 (insert (make-string ind ?\ )
1379 (make-string (string-width s) underline)
1380 "\n"))))
1382 (defvar org-table-colgroup-info nil)
1383 (defun org-format-table-generic (lines)
1384 "Format a table for ascii export."
1385 (if (stringp lines)
1386 (setq lines (org-split-string lines "\n")))
1387 (if (not (string-match "^[ \t]*|" (car lines)))
1388 ;; Table made by table.el - test for spanning
1389 lines
1391 ;; A normal org table
1392 ;; Get rid of hlines at beginning and end
1393 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1394 (setq lines (nreverse lines))
1395 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1396 (setq lines (nreverse lines))
1397 (when org-export-table-remove-special-lines
1398 ;; Check if the table has a marking column. If yes remove the
1399 ;; column and the special lines
1400 (setq lines (org-table-clean-before-export lines)))
1401 ;; Get rid of the vertical lines except for grouping
1402 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
1403 (rtn (list bodytablestart)) line vl1 start)
1404 (while (setq line (pop lines))
1405 (setq line (concat bodytablerowstart line))
1406 (if (string-match org-table-hline-regexp line)
1407 (and (string-match "|\\(.*\\)|" line)
1408 (setq line (replace-match (concat bodytablehlinestart bodytablehlineend) t nil line)))
1409 (setq start 0 vl1 vl)
1410 (if (string-match "|\\(.*\\)|" line)
1411 (setq line (replace-match (concat bodytablefirstcellstart bodytablecellstart " \\1 " bodytablecellend bodytablelastcellend) t nil line)))
1412 (while (string-match "|" line start)
1413 (setq start (+ (match-end 0) (length (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart))))
1414 (or (pop vl1) (setq line (replace-match (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart) t t line)))))
1415 (setq line (concat line bodytablerowend))
1416 (push line rtn))
1417 (setq rtn (cons bodytableend rtn))
1418 (nreverse rtn))))
1420 (defun org-colgroup-info-to-vline-list (info)
1421 (let (vl new last)
1422 (while info
1423 (setq last new new (pop info))
1424 (if (or (memq last '(:end :startend))
1425 (memq new '(:start :startend)))
1426 (push t vl)
1427 (push nil vl)))
1428 (setq vl (nreverse vl))
1429 (and vl (setcar vl nil))
1430 vl))
1433 ;;; FIXME: this should probably turn into a defconstant later [2010/05/20:rpg]
1434 (defvar org-export-generic-emphasis-alist
1435 '(("*" format-boldify nil)
1436 ("/" format-italicize nil)
1437 ("_" format-underline nil)
1438 ("+" format-strikethrough nil)
1439 ("=" format-code t)
1440 ("~" format-verbatim t))
1441 "Alist of org format -> formatting variables for fontification.
1442 Each element of the list is a list of three elements.
1443 The first element is the character used as a marker for fontification.
1444 The second element is a variable name, set in org-export-generic. That
1445 variable will be dereferenced to obtain a formatting string to wrap
1446 fontified text with.
1447 The third element decides whether to protect converted text from other
1448 conversions.")
1450 ;;; Cargo-culted from the latex translation. I couldn't figure out how
1451 ;;; to keep the structure since the generic export operates on lines, rather
1452 ;;; than on a buffer as in the latex export, meaning that none of the
1453 ;;; search forward code could be kept. This led me to rewrite the
1454 ;;; whole thing recursively. A huge lose for efficiency (potentially),
1455 ;;; but I couldn't figure out how to make the looping work.
1456 ;;; Worse, it's /doubly/ recursive, because this function calls
1457 ;;; org-export-generic-emph-format, which can call it recursively...
1458 ;;; [2010/05/20:rpg]
1459 (defun org-export-generic-fontify (string)
1460 "Convert fontification according to generic rules."
1461 (if (string-match org-emph-re string)
1462 ;; The match goes one char after the *string*, except at the end of a line
1463 (let ((emph (assoc (match-string 3 string)
1464 org-export-generic-emphasis-alist))
1465 (beg (match-beginning 0))
1466 (end (match-end 0)))
1467 (unless emph
1468 (message "`org-export-generic-emphasis-alist' has no entry for formatting triggered by \"%s\""
1469 (match-string 3 string)))
1470 ;; now we need to determine whether we have strikethrough or
1471 ;; a list, which is a bit nasty
1472 (if (and (equal (match-string 3 string) "+")
1473 (save-match-data
1474 (string-match "\\`-+\\'" (match-string 4 string))))
1475 ;; a list --- skip this match and recurse on the point after the
1476 ;; first emph char...
1477 (concat (substring string 0 (1+ (match-beginning 3)))
1478 (org-export-generic-fontify (substring string (match-beginning 3))))
1479 (concat (substring string 0 beg) ;; part before the match
1480 (match-string 1 string)
1481 (org-export-generic-emph-format (second emph)
1482 (match-string 4 string)
1483 (third emph))
1484 (or (match-string 5 string) "")
1485 (org-export-generic-fontify (substring string end)))))
1486 string))
1488 (defun org-export-generic-emph-format (format-varname string protect)
1489 "Return a string that results from applying the markup indicated by
1490 FORMAT-VARNAME to STRING."
1491 (let ((format (symbol-value format-varname)))
1492 (let ((string-to-emphasize
1493 (if protect
1494 string
1495 (org-export-generic-fontify string))))
1496 (if format
1497 (format format string-to-emphasize)
1498 string-to-emphasize))))
1500 (provide 'org-generic)
1501 (provide 'org-export-generic)
1503 ;;; org-export-generic.el ends here