org-export-generic.el: Warn about not using this for new exporters.
[org-mode.git] / contrib / lisp / org-export-generic.el
blobd04105c3d11a977df6a408f378adbaab2ef349b4
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 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 ;; IMPORTANT: IF YOU WANT TO WRITE A NEW EXPORTER FOR ORG, PLEASE
31 ;; CHECK contrib/lisp/org-export.el -- ORG-EXPORT-GENERIC.EL, WHILE
32 ;; STILL USEFUL, SHOULD NOT BE USED FOR NEW EXPORTERS.
34 ;; org-export-generic is basically a simple translation system that
35 ;; knows how to parse at least most of a .org buffer and then add
36 ;; various formatting prefixes before and after each section type. It
37 ;; does this by examining a property list stored in org-generic-alist.
38 ;; You can dynamically add propety lists of your own using the
39 ;; org-set-generic-type function:
41 ;; (org-set-generic-type
42 ;; "really-basic-text"
43 ;; '(:file-suffix ".txt"
44 ;; :key-binding ?R
46 ;; :title-format "=== %s ===\n"
47 ;; :body-header-section-numbers t
48 ;; :body-header-section-number-format "%s) "
49 ;; :body-section-header-prefix "\n"
50 ;; :body-section-header-suffix "\n"
51 ;; :body-line-format " %s\n"
52 ;; :body-line-wrap 75
53 ;; ))
55 ;; Note: Upper case key-bindings are reserved for your use. Lower
56 ;; case key bindings may conflict with future export-generic
57 ;; publications.
59 ;; Then run org-export (ctrl-c ctrl-e) and select generic or run
60 ;; org-export-generic. You'll then be prompted with a list of export
61 ;; types to choose from which will include your new type assigned to
62 ;; the key "r".
64 ;; ----------------------------------------------------------------------
66 ;; TODO (non-ordered)
67 ;; * handle function references
68 ;; * handle other types of multi-complex-listy-things to do
69 ;; ideas: (t ?- "%s" ?-)
70 ;; * handle indent specifiers better
71 ;; ideas: (4 ?\ "%s")
72 ;; * need flag to remove indents from body text
73 ;; * handle links
74 ;; * handle internationalization strings better
75 ;; * date/author/etc needs improvment (internationalization too)
76 ;; * allow specifying of section ordering
77 ;; ideas: :ordering ("header" "toc" "body" "footer")
78 ;; ^ matches current hard coded ordering
79 ;; * err, actually *do* a footer
80 ;; * deal with usage of org globals
81 ;; *** should we even consider them, or let the per-section specifiers do it
82 ;; *** answer: remove; mostly removed now
83 ;; * deal with interactive support for picking a export specifier label
84 ;; * char specifiers that need extra length because of formatting
85 ;; idea: (?- 4) for 4-longer
86 ;; * centering specifier
87 ;; idea: ('center " -- %s -- ")
88 ;; * remove more of the unneeded export-to-ascii copy code
89 ;; * tags
90 ;; *** supported now, but need separate format per tag
91 ;; *** allow different open/closing prefixes
92 ;; * properties
93 ;; * drawers
94 ;; * Escape camel-case for wiki exporters.
95 ;; * Adjust to depth limits on headers --- need to roll-over from headers
96 ;; to lists, as per other exporters
97 ;; * optmization (many plist extracts should be in let vars)
98 ;; * define defcustom spec for the specifier list
99 ;; * fonts: at least monospace is not handled at all here.
101 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
103 ;;; Commentary:
105 (require 'org-exp)
106 (require 'assoc)
107 (eval-when-compile (require 'cl))
109 (defgroup org-export-generic nil
110 "Options specific for ASCII export of Org-mode files."
111 :tag "Org Export ASCII"
112 :group 'org-export)
114 (defcustom org-export-generic-links-to-notes t
115 "Non-nil means convert links to notes before the next headline.
116 When nil, the link will be exported in place. If the line becomes long
117 in this way, it will be wrapped."
118 :group 'org-export-generic
119 :type 'boolean)
122 (defvar org-generic-current-indentation nil) ; For communication
124 (defvar org-generic-alist
127 ;; generic DEMO exporter
129 ;; (this tries to use every specifier for demo purposes)
131 ("demo"
132 :file-suffix ".txt"
133 :key-binding ?d
135 :header-prefix "<header>\n"
136 :header-suffix "</header>\n"
138 :author-export t
139 :tags-export t
141 :drawers-export t
144 :title-prefix ?=
145 :title-format "<h1>%s</h1>\n"
146 :title-suffix ?=
148 :date-export t
149 :date-prefix "<date>"
150 :date-format "<br /><b>Date:</b> <i>%s</i><br />"
151 :date-suffix "</date>\n\n"
153 :toc-export t
154 :toc-header-prefix "<tocname>\n"
155 :toc-header-format "__%s__\n"
156 :toc-header-suffix "</tocname>\n"
158 :toc-prefix "<toc>\n"
159 :toc-suffix "</toc>\n"
161 :toc-section-numbers t
162 :toc-section-number-format "\#(%s) "
163 :toc-format "--%s--"
164 :toc-format-with-todo "!!%s!!\n"
165 :toc-indent-char ?\
166 :toc-indent-depth 4
168 :toc-tags-export t
169 :toc-tags-prefix " <tags>"
170 :toc-tags-format "*%s*"
171 :toc-tags-suffix "</tags>\n"
172 :toc-tags-none-string "\n"
174 :body-header-section-numbers 3 ; t = all, nil = none
176 ; lists indicate different things per level
177 ; list contents or straight value can either be a
178 ; ?x char reference for printing strings that match the header len
179 ; "" string to print directly
180 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
181 "<h4>" "<h5>" "<h6>")
182 :body-section-header-format "%s"
183 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
184 "</h4>\n" "</h5>\n" "</h6>\n")
186 :timestamps-export t
187 :priorities-export t
188 :todo-keywords-export t
190 :body-tags-export t
191 :body-tags-prefix " <tags>"
192 :body-tags-suffix "</tags>\n"
194 ; section prefixes/suffixes can be direct strings or lists as well
195 :body-section-prefix "<secprefix>\n"
196 :body-section-suffix "</secsuffix>\n"
197 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
198 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
201 ; if preformated text should be included (eg, : prefixed)
202 :body-line-export-preformated t
203 :body-line-fixed-prefix "<pre>\n"
204 :body-line-fixed-suffix "\n</pre>\n"
205 :body-line-fixed-format "%s\n"
208 :body-list-prefix "<list>\n"
209 :body-list-suffix "</list>\n"
210 :body-list-format "<li>%s</li>\n"
212 :body-number-list-prefix "<ol>\n"
213 :body-number-list-suffix "</ol>\n"
214 :body-number-list-format "<li>%s</li>\n"
215 :body-number-list-leave-number t
217 :body-list-checkbox-todo "<checkbox type=\"todo\">"
218 :body-list-checkbox-todo-end "</checkbox (todo)>"
219 :body-list-checkbox-done "<checkbox type=\"done\">"
220 :body-list-checkbox-done-end "</checkbox (done)>"
221 :body-list-checkbox-half "<checkbox type=\"half\">"
222 :body-list-checkbox-half-end "</checkbox (half)>"
227 ; other body lines
228 :body-line-format "%s"
229 :body-line-wrap 60 ; wrap at 60 chars
231 ; print above and below all body parts
232 :body-text-prefix "<p>\n"
233 :body-text-suffix "</p>\n"
238 ;; ascii exporter
240 ;; (close to the original ascii specifier)
242 ("ascii"
243 :file-suffix ".txt"
244 :key-binding ?a
246 :header-prefix ""
247 :header-suffix ""
249 :title-prefix ?=
250 :title-format "%s\n"
251 :title-suffix ?=
253 :date-export t
254 :date-prefix ""
255 :date-format "Date: %s\n"
256 :date-suffix ""
258 :toc-header-prefix ""
259 :toc-header-format "%s\n"
260 :toc-header-suffix ?=
262 :toc-export t
263 :toc-section-numbers t
264 :toc-section-number-format "%s "
265 :toc-format "%s\n"
266 :toc-format-with-todo "%s (*)\n"
267 :toc-indent-char ?\
268 :toc-indent-depth 4
270 :body-header-section-numbers 3
271 :body-section-prefix "\n"
273 ; :body-section-header-prefix "\n"
274 ; :body-section-header-format "%s\n"
275 ; :body-section-header-suffix (?\$ ?\# ?^ ?\~ ?\= ?\-)
277 :body-section-header-prefix ("" "" "" "* " " + " " - ")
278 :body-section-header-format "%s\n"
279 :body-section-header-suffix (?~ ?= ?- "\n" "\n" "\n")
281 ; :body-section-marker-prefix ""
282 ; :body-section-marker-chars (?\$ ?\# ?^ ?\~ ?\= ?\-)
283 ; :body-section-marker-suffix "\n"
285 :body-line-export-preformated t
286 :body-line-format "%s\n"
287 :body-line-wrap 75
289 ; :body-text-prefix "<t>\n"
290 ; :body-text-suffix "</t>\n"
293 :body-bullet-list-prefix (?* ?+ ?-)
294 ; :body-bullet-list-suffix (?* ?+ ?-)
298 ;; wikipedia
300 ("wikipedia"
301 :file-suffix ".txt"
302 :key-binding ?w
304 :header-prefix ""
305 :header-suffix ""
307 :title-format "= %s =\n"
309 :date-export nil
311 :toc-export nil
313 :body-header-section-numbers nil
314 :body-section-prefix "\n"
316 :body-section-header-prefix ("= " "== " "=== "
317 "==== " "===== " "====== ")
318 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
319 " ====\n\n" " =====\n\n" " ======\n\n")
321 :body-line-export-preformated t ;; yes/no/maybe???
322 :body-line-format "%s\n"
323 :body-line-wrap 75
325 :body-line-fixed-format " %s\n"
327 :body-list-format "* %s\n"
328 :body-number-list-format "# %s\n"
330 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
333 ;; mediawiki
335 ("mediawiki"
336 :file-suffix ".txt"
337 :key-binding ?m
339 :header-prefix ""
340 :header-suffix ""
342 :title-format "= %s =\n"
344 :date-export nil
346 :toc-export nil
348 :body-header-section-numbers nil
349 :body-section-prefix "\n"
351 :body-section-header-prefix ("= " "== " "=== "
352 "==== " "===== " "====== ")
353 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
354 " ====\n\n" " =====\n\n" " ======\n\n")
356 :body-line-export-preformated t ;; yes/no/maybe???
357 :body-line-format "%s\n"
358 :body-line-wrap 75
360 :body-line-fixed-format " %s\n"
362 :body-list-format "* %s\n"
363 :body-number-list-format "# %s\n"
365 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
366 :body-list-checkbox-todo "&#9744; "
367 :body-list-checkbox-done "&#9746; "
368 :body-table-start "{|"
369 :body-table-end "|}"
370 :body-table-cell-start "|"
371 :body-table-cell-end "\n"
372 :body-table-last-cell-end "|-"
373 :body-table-hline-start ""
378 ;; internet-draft .xml for xml2rfc exporter
380 ("ietfid"
381 ;; this tries to use every specifier for demo purposes
382 :file-suffix ".xml"
383 :key-binding ?i
385 :title-prefix "<?xml version=\"1.0\"\?>
386 <!DOCTYPE rfc SYSTEM \"rfc2629.dtd\" [
387 <!ENTITY rfcs PUBLIC '' 'blah'>
388 <?rfc strict=\"yes\" ?>
389 <?rfc toc=\"yes\" ?>
390 <?rfc tocdepth=\"4\" ?>
391 <?rfc symrefs=\"yes\" ?>
392 <?rfc compact=\"yes\" ?>
393 <?rfc subcompact=\"no\" ?>
394 <rfc category=\"std\" ipr=\"pre5378Trust200902\" docName=\"FILLME.txt\">
395 <front>
397 :title-format "<title abbrev=\"ABBREV HERE\">\n%s\n</title>\n"
398 :title-suffix "<author initials=\"A.A\" surname=\"LASTNAME\" fullname=\"FULL NAME\">
399 <organization>Comany, Inc..</organization>
400 <address>
401 <postal>
402 <street></street>
403 <city></city>
404 <region></region>
405 <code></code>
406 <country></country>
407 </postal>
408 <phone></phone>
409 <email></email>
410 </address>
411 </author>
412 <date month=\"FILLMONTH\" year=\"FILLYEAR\"/>
413 <area>Operations and Management</area>
414 <workgroup>FIXME</workgroup>
415 <abstract>\n"
416 :date-export nil
418 :toc-export nil
420 :body-header-section-numbers nil
422 :body-section-header-format "<section title=\"%s\">\n"
423 :body-section-suffix "</section>\n"
425 ; if preformated text should be included (eg, : prefixed)
426 :body-line-export-preformated t
427 :body-line-fixed-prefix "<figure>\n<artwork>\n"
428 :body-line-fixed-suffix "\n</artwork>\n</figure>\n"
430 ; other body lines
431 :body-line-format "%s"
432 :body-line-wrap 75
434 ; print above and below all body parts
435 :body-text-prefix "<t>\n"
436 :body-text-suffix "</t>\n"
438 :body-list-prefix "<list style=\"symbols\">\n"
439 :body-list-suffix "</list>\n"
440 :body-list-format "<t>%s</t>\n"
443 ("trac-wiki"
444 :file-suffix ".txt"
445 :key-binding ?T
447 ;; lifted from wikipedia exporter
448 :header-prefix ""
449 :header-suffix ""
451 :title-format "= %s =\n"
453 :date-export nil
455 :toc-export nil
457 :body-header-section-numbers nil
458 :body-section-prefix "\n"
460 :body-section-header-prefix (" == " " === " " ==== "
461 " ===== " )
462 :body-section-header-suffix (" ==\n\n" " ===\n\n" " ====\n\n"
463 " =====\n\n" " ======\n\n" " =======\n\n")
465 :body-line-export-preformated t ;; yes/no/maybe???
466 :body-line-format "%s\n"
467 :body-line-wrap 75
469 :body-line-fixed-format " %s\n"
471 :body-list-format " * %s\n"
472 :body-number-list-format " # %s\n"
473 ;; :body-list-prefix "LISTSTART"
474 ;; :body-list-suffix "LISTEND"
476 ;; this is ignored! [2010/02/02:rpg]
477 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
479 ("tikiwiki"
480 :file-suffix ".txt"
481 :key-binding ?U
483 ;; lifted from wikipedia exporter
484 :header-prefix ""
485 :header-suffix ""
487 :title-format "-= %s =-\n"
489 :date-export nil
491 :toc-export nil
493 :body-header-section-numbers nil
494 :body-section-prefix "\n"
496 :body-section-header-prefix ("! " "!! " "!!! " "!!!! "
497 "!!!!! " "!!!!!! " "!!!!!!! ")
498 :body-section-header-suffix (" \n" " \n" " \n"
499 " \n" " \n" " \n")
502 :body-line-export-preformated t ;; yes/no/maybe???
503 :body-line-format "%s "
504 :body-line-wrap nil
506 :body-line-fixed-format " %s\n"
508 :body-list-format "* %s\n"
509 :body-number-list-format "# %s\n"
510 ;; :body-list-prefix "LISTSTART"
511 ;; :body-list-suffix "LISTEND"
512 :blockquote-start "\n^\n"
513 :blockquote-end "^\n\n"
514 :body-newline-paragraph "\n"
515 :bold-format "__%s__"
516 :italic-format "''%s''"
517 :underline-format "===%s==="
518 :strikethrough-format "--%s--"
519 :code-format "-+%s+-"
520 :verbatim-format "~pp~%s~/pp~"
523 "A assoc list of property lists to specify export definitions"
526 (setq org-generic-export-type "demo")
528 (defvar org-export-generic-section-type "")
529 (defvar org-export-generic-section-suffix "")
531 ;;;###autoload
532 (defun org-set-generic-type (type definition)
533 "Adds a TYPE and DEFINITION to the existing list of defined generic
534 export definitions."
535 (aput 'org-generic-alist type definition))
537 ;;; helper functions for org-set-generic-type
538 (defvar org-export-generic-keywords nil)
539 (defmacro* def-org-export-generic-keyword (keyword
540 &key documentation
541 type)
542 "Define KEYWORD as a legitimate element for inclusion in
543 the body of an org-set-generic-type definition."
544 `(progn
545 (pushnew ,keyword org-export-generic-keywords)
546 ;; TODO: push the documentation and type information
547 ;; somewhere where it will do us some good.
550 (def-org-export-generic-keyword :body-newline-paragraph
551 :documentation "Bound either to NIL or to a pattern to be
552 inserted in the output for every blank line in the input.
553 The intention is to handle formats where text is flowed, and
554 newlines are interpreted as significant \(e.g., as indicating
555 preformatted text\). A common non-nil value for this keyword
556 is \"\\n\". Should typically be combined with a value for
557 :body-line-format that does NOT end with a newline."
558 :type string)
560 ;;; fontification keywords
561 (def-org-export-generic-keyword :bold-format)
562 (def-org-export-generic-keyword :italic-format)
563 (def-org-export-generic-keyword :underline-format)
564 (def-org-export-generic-keyword :strikethrough-format)
565 (def-org-export-generic-keyword :code-format)
566 (def-org-export-generic-keyword :verbatim-format)
571 (defun org-export-generic-remember-section (type suffix &optional prefix)
572 (setq org-export-generic-section-type type)
573 (setq org-export-generic-section-suffix suffix)
574 (if prefix
575 (insert prefix))
578 (defun org-export-generic-check-section (type &optional prefix suffix)
579 "checks to see if type is already in use, or we're switching parts
580 If we're switching, then insert a potentially previously remembered
581 suffix, and insert the current prefix immediately and then save the
582 suffix a later change time."
584 (when (not (equal type org-export-generic-section-type))
585 (if org-export-generic-section-suffix
586 (insert org-export-generic-section-suffix))
587 (setq org-export-generic-section-type type)
588 (setq org-export-generic-section-suffix suffix)
589 (if prefix
590 (insert prefix))))
592 ;;;###autoload
593 (defun org-export-generic (arg)
594 "Export the outline as generic output.
595 If there is an active region, export only the region.
596 The prefix ARG specifies how many levels of the outline should become
597 underlined headlines. The default is 3."
598 (interactive "P")
599 (setq-default org-todo-line-regexp org-todo-line-regexp)
600 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
601 (org-infile-export-plist)))
602 (region-p (org-region-active-p))
603 (rbeg (and region-p (region-beginning)))
604 (rend (and region-p (region-end)))
605 (subtree-p
606 (when region-p
607 (save-excursion
608 (goto-char rbeg)
609 (and (org-at-heading-p)
610 (>= (org-end-of-subtree t t) rend)))))
611 (level-offset (if subtree-p
612 (save-excursion
613 (goto-char rbeg)
614 (+ (funcall outline-level)
615 (if org-odd-levels-only 1 0)))
617 (opt-plist (setq org-export-opt-plist
618 (if subtree-p
619 (org-export-add-subtree-options opt-plist rbeg)
620 opt-plist)))
622 helpstart
623 (bogus (mapc (lambda (x)
624 (setq helpstart
625 (concat helpstart "\["
626 (char-to-string
627 (plist-get (cdr x) :key-binding))
628 "] " (car x) "\n")))
629 org-generic-alist))
631 (help (concat helpstart "
633 \[ ] the current setting of the org-generic-export-type variable
636 (cmds
638 (append
639 (mapcar (lambda (x)
640 (list
641 (plist-get (cdr x) :key-binding)
642 (car x)))
643 org-generic-alist)
644 (list (list ? "default"))))
646 r1 r2 ass
648 ;; read in the type to use
649 (export-plist
650 (progn
651 (save-excursion
652 (save-window-excursion
653 (delete-other-windows)
654 (with-output-to-temp-buffer "*Org Export/Generic Styles Help*"
655 (princ help))
656 (org-fit-window-to-buffer (get-buffer-window
657 "*Org Export/Generic Styles Help*"))
658 (message "Select command: ")
659 (setq r1 (read-char-exclusive))))
660 (setq r2 (if (< r1 27) (+ r1 96) r1))
661 (unless (setq ass (cadr (assq r2 cmds)))
662 (error "No command associated with key %c" r1))
664 (cdr (assoc
665 (if (equal ass "default") org-generic-export-type ass)
666 org-generic-alist))))
668 (custom-times org-display-custom-times)
669 (org-generic-current-indentation '(0 . 0))
670 (level 0) (old-level 0) line txt lastwastext
671 (umax nil)
672 (umax-toc nil)
673 (case-fold-search nil)
674 (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
675 (filesuffix (or (plist-get export-plist :file-suffix) ".foo"))
676 (filename (concat (file-name-as-directory
677 (org-export-directory :ascii opt-plist))
678 (file-name-sans-extension
679 (or (and subtree-p
680 (org-entry-get (region-beginning)
681 "EXPORT_FILE_NAME" t))
682 (file-name-nondirectory bfname)))
683 filesuffix))
684 (filename (if (equal (file-truename filename)
685 (file-truename bfname))
686 (concat filename filesuffix)
687 filename))
688 (buffer (find-file-noselect filename))
689 (org-levels-open (make-vector org-level-max nil))
690 (odd org-odd-levels-only)
691 (date (plist-get opt-plist :date))
692 (author (plist-get opt-plist :author))
693 (title (or (and subtree-p (org-export-get-title-from-subtree))
694 (plist-get opt-plist :title)
695 (and (not
696 (plist-get opt-plist :skip-before-1st-heading))
697 (org-export-grab-title-from-buffer))
698 (file-name-sans-extension
699 (file-name-nondirectory bfname))))
700 (email (plist-get opt-plist :email))
701 (language (plist-get opt-plist :language))
702 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
703 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
704 (todo nil)
705 (lang-words nil)
706 (region
707 (buffer-substring
708 (if (org-region-active-p) (region-beginning) (point-min))
709 (if (org-region-active-p) (region-end) (point-max))))
710 (org-export-current-backend 'org-export-generic)
711 (lines (org-split-string
712 (org-export-preprocess-string
713 region
714 :for-backend 'ascii
715 :skip-before-1st-heading
716 (plist-get opt-plist :skip-before-1st-heading)
717 :drawers (plist-get export-plist :drawers-export)
718 :tags (plist-get export-plist :tags-export)
719 :priority (plist-get export-plist :priority-export)
720 :footnotes (plist-get export-plist :footnotes-export)
721 :timestamps (plist-get export-plist :timestamps-export)
722 :todo-keywords (plist-get export-plist :todo-keywords-export)
723 :verbatim-multiline t
724 :select-tags (plist-get export-plist :select-tags-export)
725 :exclude-tags (plist-get export-plist :exclude-tags-export)
726 :emph-multiline t
727 :archived-trees
728 (plist-get export-plist :archived-trees-export)
729 :add-text (plist-get opt-plist :text))
730 "\n"))
731 ;; export-generic plist variables
732 (withtags (plist-get export-plist :tags-export))
733 (tagsintoc (plist-get export-plist :toc-tags-export))
734 (tocnotagsstr (or (plist-get export-plist :toc-tags-none-string) ""))
735 (tocdepth (plist-get export-plist :toc-indent-depth))
736 (tocindentchar (plist-get export-plist :toc-indent-char))
737 (tocsecnums (plist-get export-plist :toc-section-numbers))
738 (tocsecnumform (plist-get export-plist :toc-section-number-format))
739 (tocformat (plist-get export-plist :toc-format))
740 (tocformtodo (plist-get export-plist :toc-format-with-todo))
741 (tocprefix (plist-get export-plist :toc-prefix))
742 (tocsuffix (plist-get export-plist :toc-suffix))
743 (bodyfixedpre (plist-get export-plist :body-line-fixed-prefix))
744 (bodyfixedsuf (plist-get export-plist :body-line-fixed-suffix))
745 (bodyfixedform (or (plist-get export-plist :body-line-fixed-format)
746 "%s"))
747 (listprefix (plist-get export-plist :body-list-prefix))
748 (listsuffix (plist-get export-plist :body-list-suffix))
749 (listformat (or (plist-get export-plist :body-list-format) "%s\n"))
750 (numlistleavenum
751 (plist-get export-plist :body-number-list-leave-number))
752 (numlistprefix (plist-get export-plist :body-number-list-prefix))
753 (numlistsuffix (plist-get export-plist :body-number-list-suffix))
754 (numlistformat
755 (or (plist-get export-plist :body-number-list-format) "%s\n"))
756 (listchecktodo
757 (or (plist-get export-plist :body-list-checkbox-todo) "\\1"))
758 (listcheckdone
759 (or (plist-get export-plist :body-list-checkbox-done) "\\1"))
760 (listcheckhalf
761 (or (plist-get export-plist :body-list-checkbox-half) "\\1"))
762 (listchecktodoend
763 (or (plist-get export-plist :body-list-checkbox-todo-end) ""))
764 (listcheckdoneend
765 (or (plist-get export-plist :body-list-checkbox-done-end) ""))
766 (listcheckhalfend
767 (or (plist-get export-plist :body-list-checkbox-half-end) ""))
768 (bodytablestart
769 (or (plist-get export-plist :body-table-start) ""))
770 (bodytableend
771 (or (plist-get export-plist :body-table-end) ""))
772 (bodytablerowstart
773 (or (plist-get export-plist :body-table-row-start) ""))
774 (bodytablerowend
775 (or (plist-get export-plist :body-table-row-end) ""))
776 (bodytablecellstart
777 (or (plist-get export-plist :body-table-cell-start) ""))
778 (bodytablecellend
779 (or (plist-get export-plist :body-table-cell-end) ""))
780 (bodytablefirstcellstart
781 (or (plist-get export-plist :body-table-first-cell-start) ""))
782 (bodytableinteriorcellstart
783 (or (plist-get export-plist :body-table-interior-cell-start) ""))
784 (bodytableinteriorcellend
785 (or (plist-get export-plist :body-table-interior-cell-end) ""))
786 (bodytablelastcellend
787 (or (plist-get export-plist :body-table-last-cell-end) ""))
788 (bodytablehlinestart
789 (or (plist-get export-plist :body-table-hline-start) " \\1"))
790 (bodytablehlineend
791 (or (plist-get export-plist :body-table-hline-end) ""))
795 (bodynewline-paragraph (plist-get export-plist :body-newline-paragraph))
796 (bodytextpre (plist-get export-plist :body-text-prefix))
797 (bodytextsuf (plist-get export-plist :body-text-suffix))
798 (bodylinewrap (plist-get export-plist :body-line-wrap))
799 (bodylineform (or (plist-get export-plist :body-line-format) "%s"))
800 (blockquotestart (or (plist-get export-plist :blockquote-start) "\n\n\t"))
801 (blockquoteend (or (plist-get export-plist :blockquote-end) "\n\n"))
803 ;; dynamic variables used heinously in fontification
804 ;; not referenced locally...
805 (format-boldify (plist-get export-plist :bold-format))
806 (format-italicize (plist-get export-plist :italic-format))
807 (format-underline (plist-get export-plist :underline-format))
808 (format-strikethrough (plist-get export-plist :strikethrough-format))
809 (format-code (plist-get export-plist :code-format))
810 (format-verbatim (plist-get export-plist :verbatim-format))
814 thetoc toctags have-headings first-heading-pos
815 table-open table-buffer link-buffer link desc desc0 rpl wrap)
817 (let ((inhibit-read-only t))
818 (org-unmodified
819 (remove-text-properties (point-min) (point-max)
820 '(:org-license-to-kill t))))
822 (setq org-min-level (org-get-min-level lines level-offset))
823 (setq org-last-level org-min-level)
824 (org-init-section-numbers)
826 (find-file-noselect filename)
828 (setq lang-words (or (assoc language org-export-language-setup)
829 (assoc "en" org-export-language-setup)))
830 (switch-to-buffer-other-window buffer)
831 (erase-buffer)
832 (fundamental-mode)
833 ;; create local variables for all options, to make sure all called
834 ;; functions get the correct information
835 (mapc (lambda (x)
836 (set (make-local-variable (nth 2 x))
837 (plist-get opt-plist (car x))))
838 org-export-plist-vars)
839 (org-set-local 'org-odd-levels-only odd)
840 (setq umax (if arg (prefix-numeric-value arg)
841 org-export-headline-levels))
842 (setq umax-toc umax)
844 ;; File header
845 (if title
846 (insert
847 (org-export-generic-header title export-plist
848 :title-prefix
849 :title-format
850 :title-suffix)))
852 (if (and (or author email)
853 (plist-get export-plist :author-export))
854 (insert (concat (nth 1 lang-words) ": " (or author "")
855 (if email (concat " <" email ">") "")
856 "\n")))
858 (cond
859 ((and date (string-match "%" date))
860 (setq date (format-time-string date)))
861 (date)
862 (t (setq date (format-time-string "%Y-%m-%d %T %Z"))))
864 (if (and date (plist-get export-plist :date-export))
865 (insert
866 (org-export-generic-header date export-plist
867 :date-prefix
868 :date-format
869 :date-suffix)))
871 ;; export the table of contents first
872 (if (plist-get export-plist :toc-export)
873 (progn
874 (push
875 (org-export-generic-header (nth 3 lang-words) export-plist
876 :toc-header-prefix
877 :toc-header-format
878 :toc-header-suffix)
879 thetoc)
881 (if tocprefix
882 (push tocprefix thetoc))
884 (mapc '(lambda (line)
885 (if (string-match org-todo-line-regexp line)
886 ;; This is a headline
887 (progn
888 (setq have-headings t)
889 (setq level (- (match-end 1) (match-beginning 1)
890 level-offset)
891 level (org-tr-level level)
892 txt (match-string 3 line)
893 todo
894 (or (and org-export-mark-todo-in-toc
895 (match-beginning 2)
896 (not (member (match-string 2 line)
897 org-done-keywords)))
898 ; TODO, not DONE
899 (and org-export-mark-todo-in-toc
900 (= level umax-toc)
901 (org-search-todo-below
902 line lines level))))
903 (setq txt (org-html-expand-for-generic txt))
905 (while (string-match org-bracket-link-regexp txt)
906 (setq txt
907 (replace-match
908 (match-string (if (match-end 2) 3 1) txt)
909 t t txt)))
911 (if (and (not tagsintoc)
912 (string-match
913 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
914 txt))
915 (setq txt (replace-match "" t t txt))
916 ; include tags but formated
917 (if (string-match
918 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$")
919 txt)
920 (progn
921 (setq
922 toctags
923 (org-export-generic-header
924 (match-string 1 txt)
925 export-plist :toc-tags-prefix
926 :toc-tags-format :toc-tags-suffix))
927 (string-match
928 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
929 txt)
930 (setq txt (replace-match "" t t txt)))
931 (setq toctags tocnotagsstr)))
933 (if (string-match quote-re0 txt)
934 (setq txt (replace-match "" t t txt)))
936 (if (<= level umax-toc)
937 (progn
938 (push
939 (concat
941 (make-string
942 (* (max 0 (- level org-min-level)) tocdepth)
943 tocindentchar)
945 (if tocsecnums
946 (format tocsecnumform
947 (org-section-number level))
950 (format
951 (if todo tocformtodo tocformat)
952 txt)
954 toctags)
956 thetoc)
957 (setq org-last-level level))
958 ))))
959 lines)
960 (if tocsuffix
961 (push tocsuffix thetoc))
962 (setq thetoc (if have-headings (nreverse thetoc) nil))))
964 (org-init-section-numbers)
965 (org-export-generic-check-section "top")
966 (while (setq line (pop lines))
967 (when (and link-buffer (string-match org-outline-regexp-bol line))
968 (org-export-generic-push-links (nreverse link-buffer))
969 (setq link-buffer nil))
970 (setq wrap nil)
971 ;; Remove the quoted HTML tags.
972 ;; XXX
973 (setq line (org-html-expand-for-generic line))
974 ;; Replace links with the description when possible
975 ;; XXX
976 (while (string-match org-bracket-link-regexp line)
977 (setq link (match-string 1 line)
978 desc0 (match-string 3 line)
979 desc (or desc0 (match-string 1 line)))
980 (if (and (> (length link) 8)
981 (equal (substring link 0 8) "coderef:"))
982 (setq line (replace-match
983 (format (org-export-get-coderef-format (substring link 8) desc)
984 (cdr (assoc
985 (substring link 8)
986 org-export-code-refs)))
987 t t line))
988 (setq rpl (concat "["
989 (or (match-string 3 line) (match-string 1 line))
990 "]"))
991 (when (and desc0 (not (equal desc0 link)))
992 (if org-export-generic-links-to-notes
993 (push (cons desc0 link) link-buffer)
994 (setq rpl (concat rpl " (" link ")")
995 wrap (+ (length line) (- (length (match-string 0 line)))
996 (length desc)))))
997 (setq line (replace-match rpl t t line))))
998 (when custom-times
999 (setq line (org-translate-time line)))
1000 (cond
1001 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
1003 ;; a Headline
1005 (org-export-generic-check-section "headline")
1007 (setq first-heading-pos (or first-heading-pos (point)))
1008 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)
1009 level-offset))
1010 txt (match-string 2 line))
1011 (org-generic-level-start level old-level txt umax export-plist lines)
1012 (setq old-level level))
1014 ((and org-export-with-tables
1015 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
1017 ;; a Table
1019 (org-export-generic-check-section "table")
1021 (if (not table-open)
1022 ;; New table starts
1023 (setq table-open t table-buffer nil))
1024 ;; Accumulate table lines
1025 (setq table-buffer (cons line table-buffer))
1026 (when (or (not lines)
1027 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
1028 (car lines))))
1029 (setq table-open nil
1030 table-buffer (nreverse table-buffer))
1031 (insert (mapconcat
1032 (lambda (x)
1033 (org-fix-indentation x org-generic-current-indentation))
1034 (org-format-table-generic table-buffer)
1035 "\n") "\n")))
1037 ((string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)
1039 ;; pre-formatted text
1041 (setq line (replace-match "\\1" nil nil line))
1043 (org-export-generic-check-section "preformat" bodyfixedpre bodyfixedsuf)
1045 (insert (format bodyfixedform line)))
1047 ((or (string-match "^\\([ \t]*\\)\\([\-\+][ \t]*\\)" line)
1048 ;; if the bullet list item is an asterisk, the leading space is /mandatory/
1049 ;; [2010/02/02:rpg]
1050 (string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
1052 ;; plain list item
1053 ;; TODO: nested lists
1055 ;; first add a line break between any previous paragraph or line item and this
1056 ;; one
1057 (when bodynewline-paragraph
1058 (insert bodynewline-paragraph))
1060 ;; I believe this gets rid of leading whitespace.
1061 (setq line (replace-match "" nil nil line))
1063 ;; won't this insert the suffix /before/ the last line of the list?
1064 ;; also isn't it spoofed by bulleted lists that have a line skip between the list items
1065 ;; unless 'org-empty-line-terminates-plain-lists' is true?
1066 (org-export-generic-check-section "liststart" listprefix listsuffix)
1068 ;; deal with checkboxes
1069 (cond
1070 ((string-match "^\\(\\[ \\]\\)[ \t]*" line)
1071 (setq line (concat (replace-match listchecktodo nil nil line)
1072 listchecktodoend)))
1073 ((string-match "^\\(\\[X\\]\\)[ \t]*" line)
1074 (setq line (concat (replace-match listcheckdone nil nil line)
1075 listcheckdoneend)))
1076 ((string-match "^\\(\\[/\\]\\)[ \t]*" line)
1077 (setq line (concat (replace-match listcheckhalf nil nil line)
1078 listcheckhalfend)))
1081 (insert (format listformat (org-export-generic-fontify line))))
1082 ((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
1084 ;; numbered list item
1086 ;; TODO: nested lists
1088 (setq line (replace-match (if numlistleavenum "\\2" "") nil nil line))
1090 (org-export-generic-check-section "numliststart"
1091 numlistprefix numlistsuffix)
1093 ;; deal with checkboxes
1094 ;; TODO: whoops; leaving the numbers is a problem for ^ matching
1095 (cond
1096 ((string-match "\\(\\[ \\]\\)[ \t]*" line)
1097 (setq line (concat (replace-match listchecktodo nil nil line)
1098 listchecktodoend)))
1099 ((string-match "\\(\\[X\\]\\)[ \t]*" line)
1100 (setq line (concat (replace-match listcheckdone nil nil line)
1101 listcheckdoneend)))
1102 ((string-match "\\(\\[/\\]\\)[ \t]*" line)
1103 (setq line (concat (replace-match listcheckhalf nil nil line)
1104 listcheckhalfend)))
1107 (insert (format numlistformat (org-export-generic-fontify line))))
1109 ((equal line "ORG-BLOCKQUOTE-START")
1110 (setq line blockquotestart))
1111 ((equal line "ORG-BLOCKQUOTE-END")
1112 (setq line blockquoteend))
1113 ((string-match "^\\s-*$" line)
1114 ;; blank line
1115 (if bodynewline-paragraph
1116 (insert bodynewline-paragraph)))
1119 ;; body
1121 (org-export-generic-check-section "body" bodytextpre bodytextsuf)
1123 (setq line
1124 (org-export-generic-fontify line))
1126 ;; XXX: properties? list?
1127 (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
1128 (setq line (replace-match "\\1\\3:" t nil line)))
1130 (setq line (org-fix-indentation line org-generic-current-indentation))
1132 ;; Remove forced line breaks
1133 (if (string-match "\\\\\\\\[ \t]*$" line)
1134 (setq line (replace-match "" t t line)))
1136 (if bodylinewrap
1137 ;; XXX: was dependent on wrap var which was calculated by???
1138 (if (> (length line) bodylinewrap)
1139 (setq line
1140 (org-export-generic-wrap line bodylinewrap))
1141 (setq line line)))
1142 (insert (format bodylineform line)))))
1144 ;; if we're at a level > 0; insert the closing body level stuff
1145 (let ((counter 0))
1146 (while (> (- level counter) 0)
1147 (insert
1148 (org-export-generic-format export-plist :body-section-suffix 0
1149 (- level counter)))
1150 (setq counter (1+ counter))))
1152 (org-export-generic-check-section "bottom")
1154 (org-export-generic-push-links (nreverse link-buffer))
1156 (normal-mode)
1158 ;; insert the table of contents
1159 (when thetoc
1160 (goto-char (point-min))
1161 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
1162 (progn
1163 (goto-char (match-beginning 0))
1164 (replace-match ""))
1165 (goto-char first-heading-pos))
1166 (mapc 'insert thetoc)
1167 (or (looking-at "[ \t]*\n[ \t]*\n")
1168 (insert "\n\n")))
1170 ;; Convert whitespace place holders
1171 (goto-char (point-min))
1172 (let (beg end)
1173 (while (setq beg (next-single-property-change (point) 'org-whitespace))
1174 (setq end (next-single-property-change beg 'org-whitespace))
1175 (goto-char beg)
1176 (delete-region beg end)
1177 (insert (make-string (- end beg) ?\ ))))
1179 (save-buffer)
1181 ;; remove display and invisible chars
1182 (let (beg end)
1183 (goto-char (point-min))
1184 (while (setq beg (next-single-property-change (point) 'display))
1185 (setq end (next-single-property-change beg 'display))
1186 (delete-region beg end)
1187 (goto-char beg)
1188 (insert "=>"))
1189 (goto-char (point-min))
1190 (while (setq beg (next-single-property-change (point) 'org-cwidth))
1191 (setq end (next-single-property-change beg 'org-cwidth))
1192 (delete-region beg end)
1193 (goto-char beg)))
1194 (goto-char (point-min))))
1197 (defun org-export-generic-format (export-plist prop &optional len n reverse)
1198 "converts a property specification to a string given types of properties
1200 The EXPORT-PLIST should be defined as the lookup plist.
1201 The PROP should be the property name to search for in it.
1202 LEN is set to the length of multi-characters strings to generate (or 0)
1203 N is the tree depth
1204 REVERSE means to reverse the list if the plist match is a list
1206 (let* ((prefixtype (plist-get export-plist prop))
1207 subtype)
1208 (cond
1209 ((null prefixtype) "")
1210 ((and len (char-or-string-p prefixtype) (not (stringp prefixtype)))
1211 ;; sequence of chars
1212 (concat (make-string len prefixtype) "\n"))
1213 ((stringp prefixtype)
1214 prefixtype)
1215 ((and n (listp prefixtype))
1216 (if reverse
1217 (setq prefixtype (reverse prefixtype)))
1218 (setq subtype (if (> n (length prefixtype))
1219 (car (last prefixtype))
1220 (nth (1- n) prefixtype)))
1221 (if (stringp subtype)
1222 subtype
1223 (concat (make-string len subtype) "\n")))
1224 (t ""))
1227 (defun org-export-generic-header (header export-plist
1228 prefixprop formatprop postfixprop
1229 &optional n reverse)
1230 "convert a header to an output string given formatting property names"
1231 (let* ((formatspec (plist-get export-plist formatprop))
1232 (len (length header)))
1233 (concat
1234 (org-export-generic-format export-plist prefixprop len n reverse)
1235 (format (or formatspec "%s") header)
1236 (org-export-generic-format export-plist postfixprop len n reverse))
1239 (defun org-export-generic-preprocess (parameters)
1240 "Do extra work for ASCII export"
1241 ;; Put quotes around verbatim text
1242 (goto-char (point-min))
1243 (while (re-search-forward org-verbatim-re nil t)
1244 (goto-char (match-end 2))
1245 (backward-delete-char 1) (insert "'")
1246 (goto-char (match-beginning 2))
1247 (delete-char 1) (insert "`")
1248 (goto-char (match-end 2)))
1249 ;; Remove target markers
1250 (goto-char (point-min))
1251 (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t)
1252 (replace-match "\\1\\2")))
1254 (defun org-html-expand-for-generic (line)
1255 "Handle quoted HTML for ASCII export."
1256 (if org-export-html-expand
1257 (while (string-match "@<[^<>\n]*>" line)
1258 ;; We just remove the tags for now.
1259 (setq line (replace-match "" nil nil line))))
1260 line)
1262 (defun org-export-generic-wrap (line where)
1263 "Wrap LINE at or before WHERE."
1264 (let* ((ind (org-get-indentation line))
1265 (indstr (make-string ind ?\ ))
1266 (len (length line))
1267 (result "")
1268 pos didfirst)
1269 (while (> len where)
1270 (catch 'found
1271 (loop for i from where downto (/ where 2) do
1272 (and (equal (aref line i) ?\ )
1273 (setq pos i)
1274 (throw 'found t))))
1275 (if pos
1276 (progn
1277 (setq result
1278 (concat result
1279 (if didfirst indstr "")
1280 (substring line 0 pos)
1281 "\n"))
1282 (setq didfirst t)
1283 (setq line (substring line (1+ pos)))
1284 (setq len (length line)))
1285 (setq result (concat result line))
1286 (setq len 0)))
1287 (concat result indstr line)))
1289 (defun org-export-generic-push-links (link-buffer)
1290 "Push out links in the buffer."
1291 (when link-buffer
1292 ;; We still have links to push out.
1293 (insert "\n")
1294 (let ((ind ""))
1295 (save-match-data
1296 (if (save-excursion
1297 (re-search-backward
1298 "^\\(\\([ \t]*\\)\\|\\(\\*+ \\)\\)[^ \t\n]" nil t))
1299 (setq ind (or (match-string 2)
1300 (make-string (length (match-string 3)) ?\ )))))
1301 (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n"))
1302 link-buffer))
1303 (insert "\n")))
1305 (defun org-generic-level-start (level old-level title umax export-plist
1306 &optional lines)
1307 "Insert a new level in a generic export."
1308 (let ((n (- level umax 1))
1309 (ind 0)
1310 (diff (- level old-level)) (counter 0)
1311 (secnums (plist-get export-plist :body-header-section-numbers))
1312 (secnumformat
1313 (plist-get export-plist :body-header-section-number-format))
1314 char tagstring)
1315 (unless org-export-with-tags
1316 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
1317 (setq title (replace-match "" t t title))))
1319 (cond
1320 ;; going deeper
1321 ((> level old-level)
1322 (while (< (+ old-level counter) (1- level))
1323 (insert
1324 (org-export-generic-format export-plist :body-section-prefix 0
1325 (+ old-level counter)))
1326 (setq counter (1+ counter))
1328 ;; going up
1329 ((< level old-level)
1330 (while (> (- old-level counter) (1- level))
1331 (insert
1332 (org-export-generic-format export-plist :body-section-suffix 0
1333 (- old-level counter)))
1334 (setq counter (1+ counter))
1336 ;; same level
1337 ((= level old-level)
1338 (insert
1339 (org-export-generic-format export-plist :body-section-suffix 0 level))
1342 (insert
1343 (org-export-generic-format export-plist :body-section-prefix 0 level))
1345 (if (and org-export-with-section-numbers
1346 secnums
1347 (or (not (numberp secnums))
1348 (< level secnums)))
1349 (setq title
1350 (concat (format (or secnumformat "%s ")
1351 (org-section-number level)) title)))
1353 ;; handle tags and formatting
1354 (if (string-match
1355 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") title)
1356 (progn
1357 (if (plist-get export-plist :body-tags-export)
1358 (setq tagstring (org-export-generic-header (match-string 1 title)
1359 export-plist
1360 :body-tags-prefix
1361 :body-tags-format
1362 :body-tags-suffix)))
1363 (string-match (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$") title)
1364 (setq title (replace-match "" t t title)))
1365 (setq tagstring (plist-get export-plist :body-tags-none-string)))
1367 (insert
1368 (org-export-generic-header title export-plist
1369 :body-section-header-prefix
1370 :body-section-header-format
1371 :body-section-header-suffix
1372 level))
1373 (if tagstring
1374 (insert tagstring))
1376 (setq org-generic-current-indentation '(0 . 0))))
1378 (defun org-insert-centered (s &optional underline)
1379 "Insert the string S centered and underline it with character UNDERLINE."
1380 (let ((ind (max (/ (- fill-column (string-width s)) 2) 0)))
1381 (insert (make-string ind ?\ ) s "\n")
1382 (if underline
1383 (insert (make-string ind ?\ )
1384 (make-string (string-width s) underline)
1385 "\n"))))
1387 (defvar org-table-colgroup-info nil)
1388 (defun org-format-table-generic (lines)
1389 "Format a table for ascii export."
1390 (if (stringp lines)
1391 (setq lines (org-split-string lines "\n")))
1392 (if (not (string-match "^[ \t]*|" (car lines)))
1393 ;; Table made by table.el - test for spanning
1394 lines
1396 ;; A normal org table
1397 ;; Get rid of hlines at beginning and end
1398 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1399 (setq lines (nreverse lines))
1400 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1401 (setq lines (nreverse lines))
1402 (when org-export-table-remove-special-lines
1403 ;; Check if the table has a marking column. If yes remove the
1404 ;; column and the special lines
1405 (setq lines (org-table-clean-before-export lines)))
1406 ;; Get rid of the vertical lines except for grouping
1407 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
1408 (rtn (list bodytablestart)) line vl1 start)
1409 (while (setq line (pop lines))
1410 (setq line (concat bodytablerowstart line))
1411 (if (string-match org-table-hline-regexp line)
1412 (and (string-match "|\\(.*\\)|" line)
1413 (setq line (replace-match (concat bodytablehlinestart bodytablehlineend) t nil line)))
1414 (setq start 0 vl1 vl)
1415 (if (string-match "|\\(.*\\)|" line)
1416 (setq line (replace-match (concat bodytablefirstcellstart bodytablecellstart " \\1 " bodytablecellend bodytablelastcellend) t nil line)))
1417 (while (string-match "|" line start)
1418 (setq start (+ (match-end 0) (length (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart))))
1419 (or (pop vl1) (setq line (replace-match (concat bodytablecellend bodytableinteriorcellend bodytableinteriorcellstart bodytablecellstart) t t line)))))
1420 (setq line (concat line bodytablerowend))
1421 (push line rtn))
1422 (setq rtn (cons bodytableend rtn))
1423 (nreverse rtn))))
1425 (defun org-colgroup-info-to-vline-list (info)
1426 (let (vl new last)
1427 (while info
1428 (setq last new new (pop info))
1429 (if (or (memq last '(:end :startend))
1430 (memq new '(:start :startend)))
1431 (push t vl)
1432 (push nil vl)))
1433 (setq vl (nreverse vl))
1434 (and vl (setcar vl nil))
1435 vl))
1438 ;;; FIXME: this should probably turn into a defconstant later [2010/05/20:rpg]
1439 (defvar org-export-generic-emphasis-alist
1440 '(("*" format-boldify nil)
1441 ("/" format-italicize nil)
1442 ("_" format-underline nil)
1443 ("+" format-strikethrough nil)
1444 ("=" format-code t)
1445 ("~" format-verbatim t))
1446 "Alist of org format -> formatting variables for fontification.
1447 Each element of the list is a list of three elements.
1448 The first element is the character used as a marker for fontification.
1449 The second element is a variable name, set in org-export-generic. That
1450 variable will be dereferenced to obtain a formatting string to wrap
1451 fontified text with.
1452 The third element decides whether to protect converted text from other
1453 conversions.")
1455 ;;; Cargo-culted from the latex translation. I couldn't figure out how
1456 ;;; to keep the structure since the generic export operates on lines, rather
1457 ;;; than on a buffer as in the latex export, meaning that none of the
1458 ;;; search forward code could be kept. This led me to rewrite the
1459 ;;; whole thing recursively. A huge lose for efficiency (potentially),
1460 ;;; but I couldn't figure out how to make the looping work.
1461 ;;; Worse, it's /doubly/ recursive, because this function calls
1462 ;;; org-export-generic-emph-format, which can call it recursively...
1463 ;;; [2010/05/20:rpg]
1464 (defun org-export-generic-fontify (string)
1465 "Convert fontification according to generic rules."
1466 (if (string-match org-emph-re string)
1467 ;; The match goes one char after the *string*, except at the end of a line
1468 (let ((emph (assoc (match-string 3 string)
1469 org-export-generic-emphasis-alist))
1470 (beg (match-beginning 0))
1471 (end (match-end 0)))
1472 (unless emph
1473 (message "`org-export-generic-emphasis-alist' has no entry for formatting triggered by \"%s\""
1474 (match-string 3 string)))
1475 ;; now we need to determine whether we have strikethrough or
1476 ;; a list, which is a bit nasty
1477 (if (and (equal (match-string 3 string) "+")
1478 (save-match-data
1479 (string-match "\\`-+\\'" (match-string 4 string))))
1480 ;; a list --- skip this match and recurse on the point after the
1481 ;; first emph char...
1482 (concat (substring string 0 (1+ (match-beginning 3)))
1483 (org-export-generic-fontify (substring string (match-beginning 3))))
1484 (concat (substring string 0 beg) ;; part before the match
1485 (match-string 1 string)
1486 (org-export-generic-emph-format (second emph)
1487 (match-string 4 string)
1488 (third emph))
1489 (or (match-string 5 string) "")
1490 (org-export-generic-fontify (substring string end)))))
1491 string))
1493 (defun org-export-generic-emph-format (format-varname string protect)
1494 "Return a string that results from applying the markup indicated by
1495 FORMAT-VARNAME to STRING."
1496 (let ((format (symbol-value format-varname)))
1497 (let ((string-to-emphasize
1498 (if protect
1499 string
1500 (org-export-generic-fontify string))))
1501 (if format
1502 (format format string-to-emphasize)
1503 string-to-emphasize))))
1505 (provide 'org-generic)
1506 (provide 'org-export-generic)
1508 ;;; org-export-generic.el ends here