4de38c793bb778d449f8b294108572d94deb586e
[org-mode.git] / contrib / lisp / org-export-generic.el
blob4de38c793bb778d449f8b294108572d94deb586e
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)
103 (eval-when-compile (require 'cl))
105 (defgroup org-export-generic nil
106 "Options specific for ASCII export of Org-mode files."
107 :tag "Org Export ASCII"
108 :group 'org-export)
110 (defcustom org-export-generic-links-to-notes t
111 "Non-nil means convert links to notes before the next headline.
112 When nil, the link will be exported in place. If the line becomes long
113 in this way, it will be wrapped."
114 :group 'org-export-generic
115 :type 'boolean)
118 (defvar org-generic-current-indentation nil) ; For communication
120 (defvar org-generic-alist
123 ;; generic DEMO exporter
125 ;; (this tries to use every specifier for demo purposes)
127 ("demo"
128 :file-suffix ".txt"
129 :key-binding ?d
131 :header-prefix "<header>\n"
132 :header-suffix "</header>\n"
134 :author-export t
135 :tags-export t
137 :drawers-export t
140 :title-prefix ?=
141 :title-format "<h1>%s</h1>\n"
142 :title-suffix ?=
144 :date-export t
145 :date-prefix "<date>"
146 :date-format "<br /><b>Date:</b> <i>%s</i><br />"
147 :date-suffix "</date>\n\n"
149 :toc-export t
150 :toc-header-prefix "<tocname>\n"
151 :toc-header-format "__%s__\n"
152 :toc-header-suffix "</tocname>\n"
154 :toc-prefix "<toc>\n"
155 :toc-suffix "</toc>\n"
157 :toc-section-numbers t
158 :toc-section-number-format "\#(%s) "
159 :toc-format "--%s--"
160 :toc-format-with-todo "!!%s!!\n"
161 :toc-indent-char ?\
162 :toc-indent-depth 4
164 :toc-tags-export t
165 :toc-tags-prefix " <tags>"
166 :toc-tags-format "*%s*"
167 :toc-tags-suffix "</tags>\n"
168 :toc-tags-none-string "\n"
170 :body-header-section-numbers 3 ; t = all, nil = none
172 ; lists indicate different things per level
173 ; list contents or straight value can either be a
174 ; ?x char reference for printing strings that match the header len
175 ; "" string to print directly
176 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
177 "<h4>" "<h5>" "<h6>")
178 :body-section-header-format "%s"
179 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
180 "</h4>\n" "</h5>\n" "</h6>\n")
182 :timestamps-export t
183 :priorities-export t
184 :todo-keywords-export t
186 :body-tags-export t
187 :body-tags-prefix " <tags>"
188 :body-tags-suffix "</tags>\n"
190 ; section prefixes/suffixes can be direct strings or lists as well
191 :body-section-prefix "<secprefix>\n"
192 :body-section-suffix "</secsuffix>\n"
193 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
194 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
197 ; if preformated text should be included (eg, : prefixed)
198 :body-line-export-preformated t
199 :body-line-fixed-prefix "<pre>\n"
200 :body-line-fixed-suffix "\n</pre>\n"
201 :body-line-fixed-format "%s\n"
204 :body-list-prefix "<list>\n"
205 :body-list-suffix "</list>\n"
206 :body-list-format "<li>%s</li>\n"
208 :body-number-list-prefix "<ol>\n"
209 :body-number-list-suffix "</ol>\n"
210 :body-number-list-format "<li>%s</li>\n"
211 :body-number-list-leave-number t
213 :body-list-checkbox-todo "<checkbox type=\"todo\">"
214 :body-list-checkbox-todo-end "</checkbox (todo)>"
215 :body-list-checkbox-done "<checkbox type=\"done\">"
216 :body-list-checkbox-done-end "</checkbox (done)>"
217 :body-list-checkbox-half "<checkbox type=\"half\">"
218 :body-list-checkbox-half-end "</checkbox (half)>"
223 ; other body lines
224 :body-line-format "%s"
225 :body-line-wrap 60 ; wrap at 60 chars
227 ; print above and below all body parts
228 :body-text-prefix "<p>\n"
229 :body-text-suffix "</p>\n"
234 ;; ascii exporter
236 ;; (close to the original ascii specifier)
238 ("ascii"
239 :file-suffix ".txt"
240 :key-binding ?a
242 :header-prefix ""
243 :header-suffix ""
245 :title-prefix ?=
246 :title-format "%s\n"
247 :title-suffix ?=
249 :date-export t
250 :date-prefix ""
251 :date-format "Date: %s\n"
252 :date-suffix ""
254 :toc-header-prefix ""
255 :toc-header-format "%s\n"
256 :toc-header-suffix ?=
258 :toc-export t
259 :toc-section-numbers t
260 :toc-section-number-format "%s "
261 :toc-format "%s\n"
262 :toc-format-with-todo "%s (*)\n"
263 :toc-indent-char ?\
264 :toc-indent-depth 4
266 :body-header-section-numbers 3
267 :body-section-prefix "\n"
269 ; :body-section-header-prefix "\n"
270 ; :body-section-header-format "%s\n"
271 ; :body-section-header-suffix (?\$ ?\# ?^ ?\~ ?\= ?\-)
273 :body-section-header-prefix ("" "" "" "* " " + " " - ")
274 :body-section-header-format "%s\n"
275 :body-section-header-suffix (?~ ?= ?- "\n" "\n" "\n")
277 ; :body-section-marker-prefix ""
278 ; :body-section-marker-chars (?\$ ?\# ?^ ?\~ ?\= ?\-)
279 ; :body-section-marker-suffix "\n"
281 :body-line-export-preformated t
282 :body-line-format "%s\n"
283 :body-line-wrap 75
285 ; :body-text-prefix "<t>\n"
286 ; :body-text-suffix "</t>\n"
289 :body-bullet-list-prefix (?* ?+ ?-)
290 ; :body-bullet-list-suffix (?* ?+ ?-)
294 ;; wikipedia
296 ("wikipedia"
297 :file-suffix ".txt"
298 :key-binding ?w
300 :header-prefix ""
301 :header-suffix ""
303 :title-format "= %s =\n"
305 :date-export nil
307 :toc-export nil
309 :body-header-section-numbers nil
310 :body-section-prefix "\n"
312 :body-section-header-prefix ("= " "== " "=== "
313 "==== " "===== " "====== ")
314 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
315 " ====\n\n" " =====\n\n" " ======\n\n")
317 :body-line-export-preformated t ;; yes/no/maybe???
318 :body-line-format "%s\n"
319 :body-line-wrap 75
321 :body-line-fixed-format " %s\n"
323 :body-list-format "* %s\n"
324 :body-number-list-format "# %s\n"
326 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
329 ;; mediawiki
331 ("mediawiki"
332 :file-suffix ".txt"
333 :key-binding ?m
335 :header-prefix ""
336 :header-suffix ""
338 :title-format "= %s =\n"
340 :date-export nil
342 :toc-export nil
344 :body-header-section-numbers nil
345 :body-section-prefix "\n"
347 :body-section-header-prefix ("= " "== " "=== "
348 "==== " "===== " "====== ")
349 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
350 " ====\n\n" " =====\n\n" " ======\n\n")
352 :body-line-export-preformated t ;; yes/no/maybe???
353 :body-line-format "%s\n"
354 :body-line-wrap 75
356 :body-line-fixed-format " %s\n"
358 :body-list-format "* %s\n"
359 :body-number-list-format "# %s\n"
361 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
362 :body-list-checkbox-todo "&#9744; "
363 :body-list-checkbox-done "&#9746; "
364 :body-table-start "{|"
365 :body-table-end "|}"
366 :body-table-cell-start "|"
367 :body-table-cell-end "\n"
368 :body-table-last-cell-end "|-"
369 :body-table-hline-start ""
374 ;; internet-draft .xml for xml2rfc exporter
376 ("ietfid"
377 ;; this tries to use every specifier for demo purposes
378 :file-suffix ".xml"
379 :key-binding ?i
381 :title-prefix "<?xml version=\"1.0\"\?>
382 <!DOCTYPE rfc SYSTEM \"rfc2629.dtd\" [
383 <!ENTITY rfcs PUBLIC '' 'blah'>
384 <?rfc strict=\"yes\" ?>
385 <?rfc toc=\"yes\" ?>
386 <?rfc tocdepth=\"4\" ?>
387 <?rfc symrefs=\"yes\" ?>
388 <?rfc compact=\"yes\" ?>
389 <?rfc subcompact=\"no\" ?>
390 <rfc category=\"std\" ipr=\"pre5378Trust200902\" docName=\"FILLME.txt\">
391 <front>
393 :title-format "<title abbrev=\"ABBREV HERE\">\n%s\n</title>\n"
394 :title-suffix "<author initials=\"A.A\" surname=\"LASTNAME\" fullname=\"FULL NAME\">
395 <organization>Comany, Inc..</organization>
396 <address>
397 <postal>
398 <street></street>
399 <city></city>
400 <region></region>
401 <code></code>
402 <country></country>
403 </postal>
404 <phone></phone>
405 <email></email>
406 </address>
407 </author>
408 <date month=\"FILLMONTH\" year=\"FILLYEAR\"/>
409 <area>Operations and Management</area>
410 <workgroup>FIXME</workgroup>
411 <abstract>\n"
412 :date-export nil
414 :toc-export nil
416 :body-header-section-numbers nil
418 :body-section-header-format "<section title=\"%s\">\n"
419 :body-section-suffix "</section>\n"
421 ; if preformated text should be included (eg, : prefixed)
422 :body-line-export-preformated t
423 :body-line-fixed-prefix "<figure>\n<artwork>\n"
424 :body-line-fixed-suffix "\n</artwork>\n</figure>\n"
426 ; other body lines
427 :body-line-format "%s"
428 :body-line-wrap 75
430 ; print above and below all body parts
431 :body-text-prefix "<t>\n"
432 :body-text-suffix "</t>\n"
434 :body-list-prefix "<list style=\"symbols\">\n"
435 :body-list-suffix "</list>\n"
436 :body-list-format "<t>%s</t>\n"
439 ("trac-wiki"
440 :file-suffix ".txt"
441 :key-binding ?T
443 ;; lifted from wikipedia exporter
444 :header-prefix ""
445 :header-suffix ""
447 :title-format "= %s =\n"
449 :date-export nil
451 :toc-export nil
453 :body-header-section-numbers nil
454 :body-section-prefix "\n"
456 :body-section-header-prefix (" == " " === " " ==== "
457 " ===== " )
458 :body-section-header-suffix (" ==\n\n" " ===\n\n" " ====\n\n"
459 " =====\n\n" " ======\n\n" " =======\n\n")
461 :body-line-export-preformated t ;; yes/no/maybe???
462 :body-line-format "%s\n"
463 :body-line-wrap 75
465 :body-line-fixed-format " %s\n"
467 :body-list-format " * %s\n"
468 :body-number-list-format " # %s\n"
469 ;; :body-list-prefix "LISTSTART"
470 ;; :body-list-suffix "LISTEND"
472 ;; this is ignored! [2010/02/02:rpg]
473 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
475 ("tikiwiki"
476 :file-suffix ".txt"
477 :key-binding ?U
479 ;; lifted from wikipedia exporter
480 :header-prefix ""
481 :header-suffix ""
483 :title-format "-= %s =-\n"
485 :date-export nil
487 :toc-export nil
489 :body-header-section-numbers nil
490 :body-section-prefix "\n"
492 :body-section-header-prefix ("! " "!! " "!!! " "!!!! "
493 "!!!!! " "!!!!!! " "!!!!!!! ")
494 :body-section-header-suffix (" \n" " \n" " \n"
495 " \n" " \n" " \n")
498 :body-line-export-preformated t ;; yes/no/maybe???
499 :body-line-format "%s "
500 :body-line-wrap nil
502 :body-line-fixed-format " %s\n"
504 :body-list-format "* %s\n"
505 :body-number-list-format "# %s\n"
506 ;; :body-list-prefix "LISTSTART"
507 ;; :body-list-suffix "LISTEND"
508 :blockquote-start "\n^\n"
509 :blockquote-end "^\n\n"
510 :body-newline-paragraph "\n"
511 :bold-format "__%s__"
512 :italic-format "''%s''"
513 :underline-format "===%s==="
514 :strikethrough-format "--%s--"
515 :code-format "-+%s+-"
516 :verbatim-format "~pp~%s~/pp~"
519 "A assoc list of property lists to specify export definitions"
522 (setq org-generic-export-type "demo")
524 (defvar org-export-generic-section-type "")
525 (defvar org-export-generic-section-suffix "")
527 ;;;###autoload
528 (defun org-set-generic-type (type definition)
529 "Adds a TYPE and DEFINITION to the existing list of defined generic
530 export definitions."
531 (aput 'org-generic-alist type definition))
533 ;;; helper functions for org-set-generic-type
534 (defvar org-export-generic-keywords nil)
535 (defmacro* def-org-export-generic-keyword (keyword
536 &key documentation
537 type)
538 "Define KEYWORD as a legitimate element for inclusion in
539 the body of an org-set-generic-type definition."
540 `(progn
541 (pushnew ,keyword org-export-generic-keywords)
542 ;; TODO: push the documentation and type information
543 ;; somewhere where it will do us some good.
546 (def-org-export-generic-keyword :body-newline-paragraph
547 :documentation "Bound either to NIL or to a pattern to be
548 inserted in the output for every blank line in the input.
549 The intention is to handle formats where text is flowed, and
550 newlines are interpreted as significant \(e.g., as indicating
551 preformatted text\). A common non-nil value for this keyword
552 is \"\\n\". Should typically be combined with a value for
553 :body-line-format that does NOT end with a newline."
554 :type string)
556 ;;; fontification keywords
557 (def-org-export-generic-keyword :bold-format)
558 (def-org-export-generic-keyword :italic-format)
559 (def-org-export-generic-keyword :underline-format)
560 (def-org-export-generic-keyword :strikethrough-format)
561 (def-org-export-generic-keyword :code-format)
562 (def-org-export-generic-keyword :verbatim-format)
567 (defun org-export-generic-remember-section (type suffix &optional prefix)
568 (setq org-export-generic-section-type type)
569 (setq org-export-generic-section-suffix suffix)
570 (if prefix
571 (insert prefix))
574 (defun org-export-generic-check-section (type &optional prefix suffix)
575 "checks to see if type is already in use, or we're switching parts
576 If we're switching, then insert a potentially previously remembered
577 suffix, and insert the current prefix immediately and then save the
578 suffix a later change time."
580 (when (not (equal type org-export-generic-section-type))
581 (if org-export-generic-section-suffix
582 (insert org-export-generic-section-suffix))
583 (setq org-export-generic-section-type type)
584 (setq org-export-generic-section-suffix suffix)
585 (if prefix
586 (insert prefix))))
588 ;;;###autoload
589 (defun org-export-generic (arg)
590 "Export the outline as generic output.
591 If there is an active region, export only the region.
592 The prefix ARG specifies how many levels of the outline should become
593 underlined headlines. The default is 3."
594 (interactive "P")
595 (setq-default org-todo-line-regexp org-todo-line-regexp)
596 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
597 (org-infile-export-plist)))
598 (region-p (org-region-active-p))
599 (rbeg (and region-p (region-beginning)))
600 (rend (and region-p (region-end)))
601 (subtree-p
602 (when region-p
603 (save-excursion
604 (goto-char rbeg)
605 (and (org-at-heading-p)
606 (>= (org-end-of-subtree t t) rend)))))
607 (level-offset (if subtree-p
608 (save-excursion
609 (goto-char rbeg)
610 (+ (funcall outline-level)
611 (if org-odd-levels-only 1 0)))
613 (opt-plist (setq org-export-opt-plist
614 (if subtree-p
615 (org-export-add-subtree-options opt-plist rbeg)
616 opt-plist)))
618 helpstart
619 (bogus (mapc (lambda (x)
620 (setq helpstart
621 (concat helpstart "\["
622 (char-to-string
623 (plist-get (cdr x) :key-binding))
624 "] " (car x) "\n")))
625 org-generic-alist))
627 (help (concat helpstart "
629 \[ ] the current setting of the org-generic-export-type variable
632 (cmds
634 (append
635 (mapcar (lambda (x)
636 (list
637 (plist-get (cdr x) :key-binding)
638 (car x)))
639 org-generic-alist)
640 (list (list ? "default"))))
642 r1 r2 ass
644 ;; read in the type to use
645 (export-plist
646 (progn
647 (save-excursion
648 (save-window-excursion
649 (delete-other-windows)
650 (with-output-to-temp-buffer "*Org Export/Generic Styles Help*"
651 (princ help))
652 (org-fit-window-to-buffer (get-buffer-window
653 "*Org Export/Generic Styles Help*"))
654 (message "Select command: ")
655 (setq r1 (read-char-exclusive))))
656 (setq r2 (if (< r1 27) (+ r1 96) r1))
657 (unless (setq ass (cadr (assq r2 cmds)))
658 (error "No command associated with key %c" r1))
660 (cdr (assoc
661 (if (equal ass "default") org-generic-export-type ass)
662 org-generic-alist))))
664 (custom-times org-display-custom-times)
665 (org-generic-current-indentation '(0 . 0))
666 (level 0) (old-level 0) line txt lastwastext
667 (umax nil)
668 (umax-toc nil)
669 (case-fold-search nil)
670 (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
671 (filesuffix (or (plist-get export-plist :file-suffix) ".foo"))
672 (filename (concat (file-name-as-directory
673 (org-export-directory :ascii opt-plist))
674 (file-name-sans-extension
675 (or (and subtree-p
676 (org-entry-get (region-beginning)
677 "EXPORT_FILE_NAME" t))
678 (file-name-nondirectory bfname)))
679 filesuffix))
680 (filename (if (equal (file-truename filename)
681 (file-truename bfname))
682 (concat filename filesuffix)
683 filename))
684 (buffer (find-file-noselect filename))
685 (org-levels-open (make-vector org-level-max nil))
686 (odd org-odd-levels-only)
687 (date (plist-get opt-plist :date))
688 (author (plist-get opt-plist :author))
689 (title (or (and subtree-p (org-export-get-title-from-subtree))
690 (plist-get opt-plist :title)
691 (and (not
692 (plist-get opt-plist :skip-before-1st-heading))
693 (org-export-grab-title-from-buffer))
694 (file-name-sans-extension
695 (file-name-nondirectory bfname))))
696 (email (plist-get opt-plist :email))
697 (language (plist-get opt-plist :language))
698 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
699 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
700 (todo nil)
701 (lang-words nil)
702 (region
703 (buffer-substring
704 (if (org-region-active-p) (region-beginning) (point-min))
705 (if (org-region-active-p) (region-end) (point-max))))
706 (org-export-current-backend 'org-export-generic)
707 (lines (org-split-string
708 (org-export-preprocess-string
709 region
710 :for-backend 'ascii
711 :skip-before-1st-heading
712 (plist-get opt-plist :skip-before-1st-heading)
713 :drawers (plist-get export-plist :drawers-export)
714 :tags (plist-get export-plist :tags-export)
715 :priority (plist-get export-plist :priority-export)
716 :footnotes (plist-get export-plist :footnotes-export)
717 :timestamps (plist-get export-plist :timestamps-export)
718 :todo-keywords (plist-get export-plist :todo-keywords-export)
719 :verbatim-multiline t
720 :select-tags (plist-get export-plist :select-tags-export)
721 :exclude-tags (plist-get export-plist :exclude-tags-export)
722 :emph-multiline t
723 :archived-trees
724 (plist-get export-plist :archived-trees-export)
725 :add-text (plist-get opt-plist :text))
726 "\n"))
727 ;; export-generic plist variables
728 (withtags (plist-get export-plist :tags-export))
729 (tagsintoc (plist-get export-plist :toc-tags-export))
730 (tocnotagsstr (or (plist-get export-plist :toc-tags-none-string) ""))
731 (tocdepth (plist-get export-plist :toc-indent-depth))
732 (tocindentchar (plist-get export-plist :toc-indent-char))
733 (tocsecnums (plist-get export-plist :toc-section-numbers))
734 (tocsecnumform (plist-get export-plist :toc-section-number-format))
735 (tocformat (plist-get export-plist :toc-format))
736 (tocformtodo (plist-get export-plist :toc-format-with-todo))
737 (tocprefix (plist-get export-plist :toc-prefix))
738 (tocsuffix (plist-get export-plist :toc-suffix))
739 (bodyfixedpre (plist-get export-plist :body-line-fixed-prefix))
740 (bodyfixedsuf (plist-get export-plist :body-line-fixed-suffix))
741 (bodyfixedform (or (plist-get export-plist :body-line-fixed-format)
742 "%s"))
743 (listprefix (plist-get export-plist :body-list-prefix))
744 (listsuffix (plist-get export-plist :body-list-suffix))
745 (listformat (or (plist-get export-plist :body-list-format) "%s\n"))
746 (numlistleavenum
747 (plist-get export-plist :body-number-list-leave-number))
748 (numlistprefix (plist-get export-plist :body-number-list-prefix))
749 (numlistsuffix (plist-get export-plist :body-number-list-suffix))
750 (numlistformat
751 (or (plist-get export-plist :body-number-list-format) "%s\n"))
752 (listchecktodo
753 (or (plist-get export-plist :body-list-checkbox-todo) "\\1"))
754 (listcheckdone
755 (or (plist-get export-plist :body-list-checkbox-done) "\\1"))
756 (listcheckhalf
757 (or (plist-get export-plist :body-list-checkbox-half) "\\1"))
758 (listchecktodoend
759 (or (plist-get export-plist :body-list-checkbox-todo-end) ""))
760 (listcheckdoneend
761 (or (plist-get export-plist :body-list-checkbox-done-end) ""))
762 (listcheckhalfend
763 (or (plist-get export-plist :body-list-checkbox-half-end) ""))
764 (bodytablestart
765 (or (plist-get export-plist :body-table-start) ""))
766 (bodytableend
767 (or (plist-get export-plist :body-table-end) ""))
768 (bodytablerowstart
769 (or (plist-get export-plist :body-table-row-start) ""))
770 (bodytablerowend
771 (or (plist-get export-plist :body-table-row-end) ""))
772 (bodytablecellstart
773 (or (plist-get export-plist :body-table-cell-start) ""))
774 (bodytablecellend
775 (or (plist-get export-plist :body-table-cell-end) ""))
776 (bodytablefirstcellstart
777 (or (plist-get export-plist :body-table-first-cell-start) ""))
778 (bodytableinteriorcellstart
779 (or (plist-get export-plist :body-table-interior-cell-start) ""))
780 (bodytableinteriorcellend
781 (or (plist-get export-plist :body-table-interior-cell-end) ""))
782 (bodytablelastcellend
783 (or (plist-get export-plist :body-table-last-cell-end) ""))
784 (bodytablehlinestart
785 (or (plist-get export-plist :body-table-hline-start) " \\1"))
786 (bodytablehlineend
787 (or (plist-get export-plist :body-table-hline-end) ""))
791 (bodynewline-paragraph (plist-get export-plist :body-newline-paragraph))
792 (bodytextpre (plist-get export-plist :body-text-prefix))
793 (bodytextsuf (plist-get export-plist :body-text-suffix))
794 (bodylinewrap (plist-get export-plist :body-line-wrap))
795 (bodylineform (or (plist-get export-plist :body-line-format) "%s"))
796 (blockquotestart (or (plist-get export-plist :blockquote-start) "\n\n\t"))
797 (blockquoteend (or (plist-get export-plist :blockquote-end) "\n\n"))
799 ;; dynamic variables used heinously in fontification
800 ;; not referenced locally...
801 (format-boldify (plist-get export-plist :bold-format))
802 (format-italicize (plist-get export-plist :italic-format))
803 (format-underline (plist-get export-plist :underline-format))
804 (format-strikethrough (plist-get export-plist :strikethrough-format))
805 (format-code (plist-get export-plist :code-format))
806 (format-verbatim (plist-get export-plist :verbatim-format))
810 thetoc toctags have-headings first-heading-pos
811 table-open table-buffer link-buffer link desc desc0 rpl wrap)
813 (let ((inhibit-read-only t))
814 (org-unmodified
815 (remove-text-properties (point-min) (point-max)
816 '(:org-license-to-kill t))))
818 (setq org-min-level (org-get-min-level lines level-offset))
819 (setq org-last-level org-min-level)
820 (org-init-section-numbers)
822 (find-file-noselect filename)
824 (setq lang-words (or (assoc language org-export-language-setup)
825 (assoc "en" org-export-language-setup)))
826 (switch-to-buffer-other-window buffer)
827 (erase-buffer)
828 (fundamental-mode)
829 ;; create local variables for all options, to make sure all called
830 ;; functions get the correct information
831 (mapc (lambda (x)
832 (set (make-local-variable (nth 2 x))
833 (plist-get opt-plist (car x))))
834 org-export-plist-vars)
835 (org-set-local 'org-odd-levels-only odd)
836 (setq umax (if arg (prefix-numeric-value arg)
837 org-export-headline-levels))
838 (setq umax-toc umax)
840 ;; File header
841 (if title
842 (insert
843 (org-export-generic-header title export-plist
844 :title-prefix
845 :title-format
846 :title-suffix)))
848 (if (and (or author email)
849 (plist-get export-plist :author-export))
850 (insert (concat (nth 1 lang-words) ": " (or author "")
851 (if email (concat " <" email ">") "")
852 "\n")))
854 (cond
855 ((and date (string-match "%" date))
856 (setq date (format-time-string date)))
857 (date)
858 (t (setq date (format-time-string "%Y-%m-%d %T %Z"))))
860 (if (and date (plist-get export-plist :date-export))
861 (insert
862 (org-export-generic-header date export-plist
863 :date-prefix
864 :date-format
865 :date-suffix)))
867 ;; export the table of contents first
868 (if (plist-get export-plist :toc-export)
869 (progn
870 (push
871 (org-export-generic-header (nth 3 lang-words) export-plist
872 :toc-header-prefix
873 :toc-header-format
874 :toc-header-suffix)
875 thetoc)
877 (if tocprefix
878 (push tocprefix thetoc))
880 (mapc '(lambda (line)
881 (if (string-match org-todo-line-regexp line)
882 ;; This is a headline
883 (progn
884 (setq have-headings t)
885 (setq level (- (match-end 1) (match-beginning 1)
886 level-offset)
887 level (org-tr-level level)
888 txt (match-string 3 line)
889 todo
890 (or (and org-export-mark-todo-in-toc
891 (match-beginning 2)
892 (not (member (match-string 2 line)
893 org-done-keywords)))
894 ; TODO, not DONE
895 (and org-export-mark-todo-in-toc
896 (= level umax-toc)
897 (org-search-todo-below
898 line lines level))))
899 (setq txt (org-html-expand-for-generic txt))
901 (while (string-match org-bracket-link-regexp txt)
902 (setq txt
903 (replace-match
904 (match-string (if (match-end 2) 3 1) txt)
905 t t txt)))
907 (if (and (not tagsintoc)
908 (string-match
909 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
910 txt))
911 (setq txt (replace-match "" t t txt))
912 ; include tags but formated
913 (if (string-match
914 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$")
915 txt)
916 (progn
917 (setq
918 toctags
919 (org-export-generic-header
920 (match-string 1 txt)
921 export-plist :toc-tags-prefix
922 :toc-tags-format :toc-tags-suffix))
923 (string-match
924 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
925 txt)
926 (setq txt (replace-match "" t t txt)))
927 (setq toctags tocnotagsstr)))
929 (if (string-match quote-re0 txt)
930 (setq txt (replace-match "" t t txt)))
932 (if (<= level umax-toc)
933 (progn
934 (push
935 (concat
937 (make-string
938 (* (max 0 (- level org-min-level)) tocdepth)
939 tocindentchar)
941 (if tocsecnums
942 (format tocsecnumform
943 (org-section-number level))
946 (format
947 (if todo tocformtodo tocformat)
948 txt)
950 toctags)
952 thetoc)
953 (setq org-last-level level))
954 ))))
955 lines)
956 (if tocsuffix
957 (push tocsuffix thetoc))
958 (setq thetoc (if have-headings (nreverse thetoc) nil))))
960 (org-init-section-numbers)
961 (org-export-generic-check-section "top")
962 (while (setq line (pop lines))
963 (when (and link-buffer (string-match org-outline-regexp-bol line))
964 (org-export-generic-push-links (nreverse link-buffer))
965 (setq link-buffer nil))
966 (setq wrap nil)
967 ;; Remove the quoted HTML tags.
968 ;; XXX
969 (setq line (org-html-expand-for-generic line))
970 ;; Replace links with the description when possible
971 ;; XXX
972 (while (string-match org-bracket-link-regexp line)
973 (setq link (match-string 1 line)
974 desc0 (match-string 3 line)
975 desc (or desc0 (match-string 1 line)))
976 (if (and (> (length link) 8)
977 (equal (substring link 0 8) "coderef:"))
978 (setq line (replace-match
979 (format (org-export-get-coderef-format (substring link 8) desc)
980 (cdr (assoc
981 (substring link 8)
982 org-export-code-refs)))
983 t t line))
984 (setq rpl (concat "["
985 (or (match-string 3 line) (match-string 1 line))
986 "]"))
987 (when (and desc0 (not (equal desc0 link)))
988 (if org-export-generic-links-to-notes
989 (push (cons desc0 link) link-buffer)
990 (setq rpl (concat rpl " (" link ")")
991 wrap (+ (length line) (- (length (match-string 0 line)))
992 (length desc)))))
993 (setq line (replace-match rpl t t line))))
994 (when custom-times
995 (setq line (org-translate-time line)))
996 (cond
997 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
999 ;; a Headline
1001 (org-export-generic-check-section "headline")
1003 (setq first-heading-pos (or first-heading-pos (point)))
1004 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)
1005 level-offset))
1006 txt (match-string 2 line))
1007 (org-generic-level-start level old-level txt umax export-plist lines)
1008 (setq old-level level))
1010 ((and org-export-with-tables
1011 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
1013 ;; a Table
1015 (org-export-generic-check-section "table")
1017 (if (not table-open)
1018 ;; New table starts
1019 (setq table-open t table-buffer nil))
1020 ;; Accumulate table lines
1021 (setq table-buffer (cons line table-buffer))
1022 (when (or (not lines)
1023 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
1024 (car lines))))
1025 (setq table-open nil
1026 table-buffer (nreverse table-buffer))
1027 (insert (mapconcat
1028 (lambda (x)
1029 (org-fix-indentation x org-generic-current-indentation))
1030 (org-format-table-generic table-buffer)
1031 "\n") "\n")))
1033 ((string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)
1035 ;; pre-formatted text
1037 (setq line (replace-match "\\1" nil nil line))
1039 (org-export-generic-check-section "preformat" bodyfixedpre bodyfixedsuf)
1041 (insert (format bodyfixedform line)))
1043 ((or (string-match "^\\([ \t]*\\)\\([\-\+][ \t]*\\)" line)
1044 ;; if the bullet list item is an asterisk, the leading space is /mandatory/
1045 ;; [2010/02/02:rpg]
1046 (string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
1048 ;; plain list item
1049 ;; TODO: nested lists
1051 ;; first add a line break between any previous paragraph or line item and this
1052 ;; one
1053 (when bodynewline-paragraph
1054 (insert bodynewline-paragraph))
1056 ;; I believe this gets rid of leading whitespace.
1057 (setq line (replace-match "" nil nil line))
1059 ;; won't this insert the suffix /before/ the last line of the list?
1060 ;; also isn't it spoofed by bulleted lists that have a line skip between the list items
1061 ;; unless 'org-empty-line-terminates-plain-lists' is true?
1062 (org-export-generic-check-section "liststart" listprefix listsuffix)
1064 ;; deal with checkboxes
1065 (cond
1066 ((string-match "^\\(\\[ \\]\\)[ \t]*" line)
1067 (setq line (concat (replace-match listchecktodo nil nil line)
1068 listchecktodoend)))
1069 ((string-match "^\\(\\[X\\]\\)[ \t]*" line)
1070 (setq line (concat (replace-match listcheckdone nil nil line)
1071 listcheckdoneend)))
1072 ((string-match "^\\(\\[/\\]\\)[ \t]*" line)
1073 (setq line (concat (replace-match listcheckhalf nil nil line)
1074 listcheckhalfend)))
1077 (insert (format listformat (org-export-generic-fontify line))))
1078 ((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
1080 ;; numbered list item
1082 ;; TODO: nested lists
1084 (setq line (replace-match (if numlistleavenum "\\2" "") nil nil line))
1086 (org-export-generic-check-section "numliststart"
1087 numlistprefix numlistsuffix)
1089 ;; deal with checkboxes
1090 ;; TODO: whoops; leaving the numbers is a problem for ^ matching
1091 (cond
1092 ((string-match "\\(\\[ \\]\\)[ \t]*" line)
1093 (setq line (concat (replace-match listchecktodo nil nil line)
1094 listchecktodoend)))
1095 ((string-match "\\(\\[X\\]\\)[ \t]*" line)
1096 (setq line (concat (replace-match listcheckdone nil nil line)
1097 listcheckdoneend)))
1098 ((string-match "\\(\\[/\\]\\)[ \t]*" line)
1099 (setq line (concat (replace-match listcheckhalf nil nil line)
1100 listcheckhalfend)))
1103 (insert (format numlistformat (org-export-generic-fontify line))))
1105 ((equal line "ORG-BLOCKQUOTE-START")
1106 (setq line blockquotestart))
1107 ((equal line "ORG-BLOCKQUOTE-END")
1108 (setq line blockquoteend))
1109 ((string-match "^\\s-*$" line)
1110 ;; blank line
1111 (if bodynewline-paragraph
1112 (insert bodynewline-paragraph)))
1115 ;; body
1117 (org-export-generic-check-section "body" bodytextpre bodytextsuf)
1119 (setq line
1120 (org-export-generic-fontify line))
1122 ;; XXX: properties? list?
1123 (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
1124 (setq line (replace-match "\\1\\3:" t nil line)))
1126 (setq line (org-fix-indentation line org-generic-current-indentation))
1128 ;; Remove forced line breaks
1129 (if (string-match "\\\\\\\\[ \t]*$" line)
1130 (setq line (replace-match "" t t line)))
1132 (if bodylinewrap
1133 ;; XXX: was dependent on wrap var which was calculated by???
1134 (if (> (length line) bodylinewrap)
1135 (setq line
1136 (org-export-generic-wrap line bodylinewrap))
1137 (setq line line)))
1138 (insert (format bodylineform line)))))
1140 ;; if we're at a level > 0; insert the closing body level stuff
1141 (let ((counter 0))
1142 (while (> (- level counter) 0)
1143 (insert
1144 (org-export-generic-format export-plist :body-section-suffix 0
1145 (- level counter)))
1146 (setq counter (1+ counter))))
1148 (org-export-generic-check-section "bottom")
1150 (org-export-generic-push-links (nreverse link-buffer))
1152 (normal-mode)
1154 ;; insert the table of contents
1155 (when thetoc
1156 (goto-char (point-min))
1157 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
1158 (progn
1159 (goto-char (match-beginning 0))
1160 (replace-match ""))
1161 (goto-char first-heading-pos))
1162 (mapc 'insert thetoc)
1163 (or (looking-at "[ \t]*\n[ \t]*\n")
1164 (insert "\n\n")))
1166 ;; Convert whitespace place holders
1167 (goto-char (point-min))
1168 (let (beg end)
1169 (while (setq beg (next-single-property-change (point) 'org-whitespace))
1170 (setq end (next-single-property-change beg 'org-whitespace))
1171 (goto-char beg)
1172 (delete-region beg end)
1173 (insert (make-string (- end beg) ?\ ))))
1175 (save-buffer)
1177 ;; remove display and invisible chars
1178 (let (beg end)
1179 (goto-char (point-min))
1180 (while (setq beg (next-single-property-change (point) 'display))
1181 (setq end (next-single-property-change beg 'display))
1182 (delete-region beg end)
1183 (goto-char beg)
1184 (insert "=>"))
1185 (goto-char (point-min))
1186 (while (setq beg (next-single-property-change (point) 'org-cwidth))
1187 (setq end (next-single-property-change beg 'org-cwidth))
1188 (delete-region beg end)
1189 (goto-char beg)))
1190 (goto-char (point-min))))
1193 (defun org-export-generic-format (export-plist prop &optional len n reverse)
1194 "converts a property specification to a string given types of properties
1196 The EXPORT-PLIST should be defined as the lookup plist.
1197 The PROP should be the property name to search for in it.
1198 LEN is set to the length of multi-characters strings to generate (or 0)
1199 N is the tree depth
1200 REVERSE means to reverse the list if the plist match is a list
1202 (let* ((prefixtype (plist-get export-plist prop))
1203 subtype)
1204 (cond
1205 ((null prefixtype) "")
1206 ((and len (char-or-string-p prefixtype) (not (stringp prefixtype)))
1207 ;; sequence of chars
1208 (concat (make-string len prefixtype) "\n"))
1209 ((stringp prefixtype)
1210 prefixtype)
1211 ((and n (listp prefixtype))
1212 (if reverse
1213 (setq prefixtype (reverse prefixtype)))
1214 (setq subtype (if (> n (length prefixtype))
1215 (car (last prefixtype))
1216 (nth (1- n) prefixtype)))
1217 (if (stringp subtype)
1218 subtype
1219 (concat (make-string len subtype) "\n")))
1220 (t ""))
1223 (defun org-export-generic-header (header export-plist
1224 prefixprop formatprop postfixprop
1225 &optional n reverse)
1226 "convert a header to an output string given formatting property names"
1227 (let* ((formatspec (plist-get export-plist formatprop))
1228 (len (length header)))
1229 (concat
1230 (org-export-generic-format export-plist prefixprop len n reverse)
1231 (format (or formatspec "%s") header)
1232 (org-export-generic-format export-plist postfixprop len n reverse))
1235 (defun org-export-generic-preprocess (parameters)
1236 "Do extra work for ASCII export"
1237 ;; Put quotes around verbatim text
1238 (goto-char (point-min))
1239 (while (re-search-forward org-verbatim-re nil t)
1240 (goto-char (match-end 2))
1241 (backward-delete-char 1) (insert "'")
1242 (goto-char (match-beginning 2))
1243 (delete-char 1) (insert "`")
1244 (goto-char (match-end 2)))
1245 ;; Remove target markers
1246 (goto-char (point-min))
1247 (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t)
1248 (replace-match "\\1\\2")))
1250 (defun org-html-expand-for-generic (line)
1251 "Handle quoted HTML for ASCII export."
1252 (if org-export-html-expand
1253 (while (string-match "@<[^<>\n]*>" line)
1254 ;; We just remove the tags for now.
1255 (setq line (replace-match "" nil nil line))))
1256 line)
1258 (defun org-export-generic-wrap (line where)
1259 "Wrap LINE at or before WHERE."
1260 (let* ((ind (org-get-indentation line))
1261 (indstr (make-string ind ?\ ))
1262 (len (length line))
1263 (result "")
1264 pos didfirst)
1265 (while (> len where)
1266 (catch 'found
1267 (loop for i from where downto (/ where 2) do
1268 (and (equal (aref line i) ?\ )
1269 (setq pos i)
1270 (throw 'found t))))
1271 (if pos
1272 (progn
1273 (setq result
1274 (concat result
1275 (if didfirst indstr "")
1276 (substring line 0 pos)
1277 "\n"))
1278 (setq didfirst t)
1279 (setq line (substring line (1+ pos)))
1280 (setq len (length line)))
1281 (setq result (concat result line))
1282 (setq len 0)))
1283 (concat result indstr line)))
1285 (defun org-export-generic-push-links (link-buffer)
1286 "Push out links in the buffer."
1287 (when link-buffer
1288 ;; We still have links to push out.
1289 (insert "\n")
1290 (let ((ind ""))
1291 (save-match-data
1292 (if (save-excursion
1293 (re-search-backward
1294 "^\\(\\([ \t]*\\)\\|\\(\\*+ \\)\\)[^ \t\n]" nil t))
1295 (setq ind (or (match-string 2)
1296 (make-string (length (match-string 3)) ?\ )))))
1297 (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n"))
1298 link-buffer))
1299 (insert "\n")))
1301 (defun org-generic-level-start (level old-level title umax export-plist
1302 &optional lines)
1303 "Insert a new level in a generic export."
1304 (let ((n (- level umax 1))
1305 (ind 0)
1306 (diff (- level old-level)) (counter 0)
1307 (secnums (plist-get export-plist :body-header-section-numbers))
1308 (secnumformat
1309 (plist-get export-plist :body-header-section-number-format))
1310 char tagstring)
1311 (unless org-export-with-tags
1312 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
1313 (setq title (replace-match "" t t title))))
1315 (cond
1316 ;; going deeper
1317 ((> level old-level)
1318 (while (< (+ old-level counter) (1- level))
1319 (insert
1320 (org-export-generic-format export-plist :body-section-prefix 0
1321 (+ old-level counter)))
1322 (setq counter (1+ counter))
1324 ;; going up
1325 ((< level old-level)
1326 (while (> (- old-level counter) (1- level))
1327 (insert
1328 (org-export-generic-format export-plist :body-section-suffix 0
1329 (- old-level counter)))
1330 (setq counter (1+ counter))
1332 ;; same level
1333 ((= level old-level)
1334 (insert
1335 (org-export-generic-format export-plist :body-section-suffix 0 level))
1338 (insert
1339 (org-export-generic-format export-plist :body-section-prefix 0 level))
1341 (if (and org-export-with-section-numbers
1342 secnums
1343 (or (not (numberp secnums))
1344 (< level secnums)))
1345 (setq title
1346 (concat (format (or secnumformat "%s ")
1347 (org-section-number level)) title)))
1349 ;; handle tags and formatting
1350 (if (string-match
1351 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") title)
1352 (progn
1353 (if (plist-get export-plist :body-tags-export)
1354 (setq tagstring (org-export-generic-header (match-string 1 title)
1355 export-plist
1356 :body-tags-prefix
1357 :body-tags-format
1358 :body-tags-suffix)))
1359 (string-match (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$") title)
1360 (setq title (replace-match "" t t title)))
1361 (setq tagstring (plist-get export-plist :body-tags-none-string)))
1363 (insert
1364 (org-export-generic-header title export-plist
1365 :body-section-header-prefix
1366 :body-section-header-format
1367 :body-section-header-suffix
1368 level))
1369 (if tagstring
1370 (insert tagstring))
1372 (setq org-generic-current-indentation '(0 . 0))))
1374 (defun org-insert-centered (s &optional underline)
1375 "Insert the string S centered and underline it with character UNDERLINE."
1376 (let ((ind (max (/ (- fill-column (string-width s)) 2) 0)))
1377 (insert (make-string ind ?\ ) s "\n")
1378 (if underline
1379 (insert (make-string ind ?\ )
1380 (make-string (string-width s) underline)
1381 "\n"))))
1383 (defvar org-table-colgroup-info nil)
1384 (defun org-format-table-generic (lines)
1385 "Format a table for ascii export."
1386 (if (stringp lines)
1387 (setq lines (org-split-string lines "\n")))
1388 (if (not (string-match "^[ \t]*|" (car lines)))
1389 ;; Table made by table.el - test for spanning
1390 lines
1392 ;; A normal org table
1393 ;; Get rid of hlines at beginning and end
1394 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1395 (setq lines (nreverse lines))
1396 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1397 (setq lines (nreverse lines))
1398 (when org-export-table-remove-special-lines
1399 ;; Check if the table has a marking column. If yes remove the
1400 ;; column and the special lines
1401 (setq lines (org-table-clean-before-export lines)))
1402 ;; Get rid of the vertical lines except for grouping
1403 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
1404 (rtn (list bodytablestart)) line vl1 start)
1405 (while (setq line (pop lines))
1406 (setq line (concat bodytablerowstart line))
1407 (if (string-match org-table-hline-regexp line)
1408 (and (string-match "|\\(.*\\)|" line)
1409 (setq line (replace-match (concat bodytablehlinestart bodytablehlineend) t nil line)))
1410 (setq start 0 vl1 vl)
1411 (if (string-match "|\\(.*\\)|" line)
1412 (setq line (replace-match (concat bodytablefirstcellstart bodytablecellstart " \\1 " bodytablecellend bodytablelastcellend) t nil line)))
1413 (while (string-match "|" line start)
1414 (setq start (+ (match-end 0) (length (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart))))
1415 (or (pop vl1) (setq line (replace-match (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart) t t line)))))
1416 (setq line (concat line bodytablerowend))
1417 (push line rtn))
1418 (setq rtn (cons bodytableend rtn))
1419 (nreverse rtn))))
1421 (defun org-colgroup-info-to-vline-list (info)
1422 (let (vl new last)
1423 (while info
1424 (setq last new new (pop info))
1425 (if (or (memq last '(:end :startend))
1426 (memq new '(:start :startend)))
1427 (push t vl)
1428 (push nil vl)))
1429 (setq vl (nreverse vl))
1430 (and vl (setcar vl nil))
1431 vl))
1434 ;;; FIXME: this should probably turn into a defconstant later [2010/05/20:rpg]
1435 (defvar org-export-generic-emphasis-alist
1436 '(("*" format-boldify nil)
1437 ("/" format-italicize nil)
1438 ("_" format-underline nil)
1439 ("+" format-strikethrough nil)
1440 ("=" format-code t)
1441 ("~" format-verbatim t))
1442 "Alist of org format -> formatting variables for fontification.
1443 Each element of the list is a list of three elements.
1444 The first element is the character used as a marker for fontification.
1445 The second element is a variable name, set in org-export-generic. That
1446 variable will be dereferenced to obtain a formatting string to wrap
1447 fontified text with.
1448 The third element decides whether to protect converted text from other
1449 conversions.")
1451 ;;; Cargo-culted from the latex translation. I couldn't figure out how
1452 ;;; to keep the structure since the generic export operates on lines, rather
1453 ;;; than on a buffer as in the latex export, meaning that none of the
1454 ;;; search forward code could be kept. This led me to rewrite the
1455 ;;; whole thing recursively. A huge lose for efficiency (potentially),
1456 ;;; but I couldn't figure out how to make the looping work.
1457 ;;; Worse, it's /doubly/ recursive, because this function calls
1458 ;;; org-export-generic-emph-format, which can call it recursively...
1459 ;;; [2010/05/20:rpg]
1460 (defun org-export-generic-fontify (string)
1461 "Convert fontification according to generic rules."
1462 (if (string-match org-emph-re string)
1463 ;; The match goes one char after the *string*, except at the end of a line
1464 (let ((emph (assoc (match-string 3 string)
1465 org-export-generic-emphasis-alist))
1466 (beg (match-beginning 0))
1467 (end (match-end 0)))
1468 (unless emph
1469 (message "`org-export-generic-emphasis-alist' has no entry for formatting triggered by \"%s\""
1470 (match-string 3 string)))
1471 ;; now we need to determine whether we have strikethrough or
1472 ;; a list, which is a bit nasty
1473 (if (and (equal (match-string 3 string) "+")
1474 (save-match-data
1475 (string-match "\\`-+\\'" (match-string 4 string))))
1476 ;; a list --- skip this match and recurse on the point after the
1477 ;; first emph char...
1478 (concat (substring string 0 (1+ (match-beginning 3)))
1479 (org-export-generic-fontify (substring string (match-beginning 3))))
1480 (concat (substring string 0 beg) ;; part before the match
1481 (match-string 1 string)
1482 (org-export-generic-emph-format (second emph)
1483 (match-string 4 string)
1484 (third emph))
1485 (or (match-string 5 string) "")
1486 (org-export-generic-fontify (substring string end)))))
1487 string))
1489 (defun org-export-generic-emph-format (format-varname string protect)
1490 "Return a string that results from applying the markup indicated by
1491 FORMAT-VARNAME to STRING."
1492 (let ((format (symbol-value format-varname)))
1493 (let ((string-to-emphasize
1494 (if protect
1495 string
1496 (org-export-generic-fontify string))))
1497 (if format
1498 (format format string-to-emphasize)
1499 string-to-emphasize))))
1501 (provide 'org-generic)
1502 (provide 'org-export-generic)
1504 ;;; org-export-generic.el ends here