babel: smarter `org-babel-ref-split-args' -- fixes bug parsing indexed function-style...
[rgr-org-mode.git] / contrib / lisp / org-export-generic.el
blob11c37da4ee6c3ca3cf4b4d28ce9e7e5ec4385e9b
1 ;;; org-export-generic.el --- Export frameworg with custom backends
3 ;; Copyright (C) 2009 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 ;; * oh my
91 ;; * optmization (many plist extracts should be in (let) vars
92 ;; * define defcustom spec for the specifier list
94 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
96 ;;; Commentary:
98 (require 'org-exp)
99 (require 'assoc)
101 (defgroup org-export-generic nil
102 "Options specific for ASCII export of Org-mode files."
103 :tag "Org Export ASCII"
104 :group 'org-export)
106 (defcustom org-export-generic-links-to-notes t
107 "Non-nil means convert links to notes before the next headline.
108 When nil, the link will be exported in place. If the line becomes long
109 in this way, it will be wrapped."
110 :group 'org-export-generic
111 :type 'boolean)
114 (defvar org-generic-current-indentation nil) ; For communication
116 (defvar org-generic-alist
119 ;; generic DEMO exporter
121 ;; (this tries to use every specifier for demo purposes)
123 ("demo"
124 :file-suffix ".txt"
125 :key-binding ?d
127 :header-prefix "<header>\n"
128 :header-suffix "</header>\n"
130 :author-export t
131 :tags-export t
133 :drawers-export t
136 :title-prefix ?=
137 :title-format "<h1>%s</h1>\n"
138 :title-suffix ?=
140 :date-export t
141 :date-prefix "<date>"
142 :date-format "<br /><b>Date:</b> <i>%s</i><br />"
143 :date-suffix "</date>\n\n"
145 :toc-export t
146 :toc-header-prefix "<tocname>\n"
147 :toc-header-format "__%s__\n"
148 :toc-header-suffix "</tocname>\n"
150 :toc-prefix "<toc>\n"
151 :toc-suffix "</toc>\n"
153 :toc-section-numbers t
154 :toc-section-number-format "\#(%s) "
155 :toc-format "--%s--"
156 :toc-format-with-todo "!!%s!!\n"
157 :toc-indent-char ?\
158 :toc-indent-depth 4
160 :toc-tags-export t
161 :toc-tags-prefix " <tags>"
162 :toc-tags-format "*%s*"
163 :toc-tags-suffix "</tags>\n"
164 :toc-tags-none-string "\n"
166 :body-header-section-numbers 3 ; t = all, nil = none
168 ; lists indicate different things per level
169 ; list contents or straight value can either be a
170 ; ?x char reference for printing strings that match the header len
171 ; "" string to print directly
172 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
173 "<h4>" "<h5>" "<h6>")
174 :body-section-header-format "%s"
175 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
176 "</h4>\n" "</h5>\n" "</h6>\n")
178 :timestamps-export t
179 :priorities-export t
180 :todo-keywords-export t
182 :body-tags-export t
183 :body-tags-prefix " <tags>"
184 :body-tags-suffix "</tags>\n"
186 ; section prefixes/suffixes can be direct strings or lists as well
187 :body-section-prefix "<secprefix>\n"
188 :body-section-suffix "</secsuffix>\n"
189 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
190 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
193 ; if preformated text should be included (eg, : prefixed)
194 :body-line-export-preformated t
195 :body-line-fixed-prefix "<pre>\n"
196 :body-line-fixed-suffix "\n</pre>\n"
197 :body-line-fixed-format "%s\n"
200 :body-list-prefix "<list>\n"
201 :body-list-suffix "</list>\n"
202 :body-list-format "<li>%s</li>\n"
204 :body-number-list-prefix "<ol>\n"
205 :body-number-list-suffix "</ol>\n"
206 :body-number-list-format "<li>%s</li>\n"
207 :body-number-list-leave-number t
209 :body-list-checkbox-todo "<checkbox type=\"todo\">"
210 :body-list-checkbox-todo-end "</checkbox (todo)>"
211 :body-list-checkbox-done "<checkbox type=\"done\">"
212 :body-list-checkbox-done-end "</checkbox (done)>"
213 :body-list-checkbox-half "<checkbox type=\"half\">"
214 :body-list-checkbox-half-end "</checkbox (half)>"
219 ; other body lines
220 :body-line-format "%s"
221 :body-line-wrap 60 ; wrap at 60 chars
223 ; print above and below all body parts
224 :body-text-prefix "<p>\n"
225 :body-text-suffix "</p>\n"
230 ;; ascii exporter
232 ;; (close to the original ascii specifier)
234 ("ascii"
235 :file-suffix ".txt"
236 :key-binding ?a
238 :header-prefix ""
239 :header-suffix ""
241 :title-prefix ?=
242 :title-format "%s\n"
243 :title-suffix ?=
245 :date-export t
246 :date-prefix ""
247 :date-format "Date: %s\n"
248 :date-suffix ""
250 :toc-header-prefix ""
251 :toc-header-format "%s\n"
252 :toc-header-suffix ?=
254 :toc-export t
255 :toc-section-numbers t
256 :toc-section-number-format "%s "
257 :toc-format "%s\n"
258 :toc-format-with-todo "%s (*)\n"
259 :toc-indent-char ?\
260 :toc-indent-depth 4
262 :body-header-section-numbers 3
263 :body-section-prefix "\n"
265 ; :body-section-header-prefix "\n"
266 ; :body-section-header-format "%s\n"
267 ; :body-section-header-suffix (?\$ ?\# ?^ ?\~ ?\= ?\-)
269 :body-section-header-prefix ("" "" "" "* " " + " " - ")
270 :body-section-header-format "%s\n"
271 :body-section-header-suffix (?~ ?= ?- "\n" "\n" "\n")
273 ; :body-section-marker-prefix ""
274 ; :body-section-marker-chars (?\$ ?\# ?^ ?\~ ?\= ?\-)
275 ; :body-section-marker-suffix "\n"
277 :body-line-export-preformated t
278 :body-line-format "%s\n"
279 :body-line-wrap 75
281 ; :body-text-prefix "<t>\n"
282 ; :body-text-suffix "</t>\n"
285 :body-bullet-list-prefix (?* ?+ ?-)
286 ; :body-bullet-list-suffix (?* ?+ ?-)
290 ;; wikipedia
292 ("wikipedia"
293 :file-suffix ".txt"
294 :key-binding ?w
296 :header-prefix ""
297 :header-suffix ""
299 :title-format "= %s =\n"
301 :date-export nil
303 :toc-export nil
305 :body-header-section-numbers nil
306 :body-section-prefix "\n"
308 :body-section-header-prefix ("= " "== " "=== "
309 "==== " "===== " "====== ")
310 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
311 " ====\n\n" " =====\n\n" " ======\n\n")
313 :body-line-export-preformated t ;; yes/no/maybe???
314 :body-line-format "%s\n"
315 :body-line-wrap 75
317 :body-line-fixed-format " %s\n"
319 :body-list-format "* %s\n"
320 :body-number-list-format "# %s\n"
322 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
326 ;; minimal html exporter
328 ("html"
329 ;; simple html output
330 :file-suffix ".html"
331 :key-binding ?h
333 :header-prefix "<body>"
335 :title-format "<h1>%s</h1>\n\n"
337 :date-export t
338 :date-format "<br /><b>Date:</b> <i>%s</i><br />\n\n"
340 :toc-export nil
342 :body-header-section-numbers 3
344 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
345 "<h4>" "<h5>" "<h6>")
346 :body-section-header-format "%s"
347 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
348 "</h4>\n" "</h5>\n" "</h6>\n")
350 :body-section-prefix "<secprefix>\n"
351 :body-section-suffix "</secsuffix>\n"
352 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
353 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
355 :body-line-export-preformated t
356 :body-line-format "%s\n"
358 :body-text-prefix "<p>\n"
359 :body-text-suffix "</p>\n"
361 :body-bullet-list-prefix (?* ?+ ?-)
362 ; :body-bullet-list-suffix (?* ?+ ?-)
366 ;; internet-draft .xml for xml2rfc exporter
368 ("ietfid"
369 ;; this tries to use every specifier for demo purposes
370 :file-suffix ".xml"
371 :key-binding ?i
373 :title-prefix "<?xml version=\"1.0\"\?>
374 <!DOCTYPE rfc SYSTEM \"rfc2629.dtd\" [
375 <!ENTITY rfcs PUBLIC '' 'blah'>
376 <?rfc strict=\"yes\" ?>
377 <?rfc toc=\"yes\" ?>
378 <?rfc tocdepth=\"4\" ?>
379 <?rfc symrefs=\"yes\" ?>
380 <?rfc compact=\"yes\" ?>
381 <?rfc subcompact=\"no\" ?>
382 <rfc category=\"std\" ipr=\"pre5378Trust200902\" docName=\"FILLME.txt\">
383 <front>
385 :title-format "<title abbrev=\"ABBREV HERE\">\n%s\n</title>\n"
386 :title-suffix "<author initials=\"A.A\" surname=\"LASTNAME\" fullname=\"FULL NAME\">
387 <organization>Comany, Inc..</organization>
388 <address>
389 <postal>
390 <street></street>
391 <city></city>
392 <region></region>
393 <code></code>
394 <country></country>
395 </postal>
396 <phone></phone>
397 <email></email>
398 </address>
399 </author>
400 <date month=\"FILLMONTH\" year=\"FILLYEAR\"/>
401 <area>Operations and Management</area>
402 <workgroup>FIXME</workgroup>
403 <abstract>\n"
404 :date-export nil
406 :toc-export nil
408 :body-header-section-numbers nil
410 :body-section-header-format "<section title=\"%s\">\n"
411 :body-section-suffix "</section>\n"
413 ; if preformated text should be included (eg, : prefixed)
414 :body-line-export-preformated t
415 :body-line-fixed-prefix "<figure>\n<artwork>\n"
416 :body-line-fixed-suffix "\n</artwork>\n</figure>\n"
418 ; other body lines
419 :body-line-format "%s"
420 :body-line-wrap 75
422 ; print above and below all body parts
423 :body-text-prefix "<t>\n"
424 :body-text-suffix "</t>\n"
426 :body-list-prefix "<list style=\"symbols\">\n"
427 :body-list-suffix "</list>\n"
428 :body-list-format "<t>%s</t>\n"
432 "A assoc list of property lists to specify export definitions"
435 (setq org-generic-export-type "demo")
437 (defvar org-export-generic-section-type "")
438 (defvar org-export-generic-section-suffix "")
440 ;;;###autoload
441 (defun org-set-generic-type (type definition)
442 "Adds a TYPE and DEFINITION to the existing list of defined generic
443 export definitions."
444 (aput 'org-generic-alist type definition))
446 (defun org-export-generic-remember-section (type suffix &optional prefix)
447 (setq org-export-generic-section-type type)
448 (setq org-export-generic-section-suffix suffix)
449 (if prefix
450 (insert prefix))
453 (defun org-export-generic-check-section (type &optional prefix suffix)
454 "checks to see if type is already in use, or we're switching parts
455 If we're switching, then insert a potentially previously remembered
456 suffix, and insert the current prefix immediately and then save the
457 suffix a later change time."
459 (when (not (equal type org-export-generic-section-type))
460 (if org-export-generic-section-suffix
461 (insert org-export-generic-section-suffix))
462 (setq org-export-generic-section-type type)
463 (setq org-export-generic-section-suffix suffix)
464 (if prefix
465 (insert prefix))))
467 ;;;###autoload
468 (defun org-export-generic (arg)
469 "Export the outline as generic output.
470 If there is an active region, export only the region.
471 The prefix ARG specifies how many levels of the outline should become
472 underlined headlines. The default is 3."
473 (interactive "P")
474 (setq-default org-todo-line-regexp org-todo-line-regexp)
475 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
476 (org-infile-export-plist)))
477 (region-p (org-region-active-p))
478 (rbeg (and region-p (region-beginning)))
479 (rend (and region-p (region-end)))
480 (subtree-p
481 (when region-p
482 (save-excursion
483 (goto-char rbeg)
484 (and (org-at-heading-p)
485 (>= (org-end-of-subtree t t) rend)))))
486 (level-offset (if subtree-p
487 (save-excursion
488 (goto-char rbeg)
489 (+ (funcall outline-level)
490 (if org-odd-levels-only 1 0)))
492 (opt-plist (setq org-export-opt-plist
493 (if subtree-p
494 (org-export-add-subtree-options opt-plist rbeg)
495 opt-plist)))
497 helpstart
498 (bogus (mapc (lambda (x)
499 (setq helpstart
500 (concat helpstart "\["
501 (char-to-string
502 (plist-get (cdr x) :key-binding))
503 "] " (car x) "\n")))
504 org-generic-alist))
506 (help (concat helpstart "
508 \[ ] the current setting of the org-generic-export-type variable
511 (cmds
513 (append
514 (mapcar (lambda (x)
515 (list
516 (plist-get (cdr x) :key-binding)
517 (car x)))
518 org-generic-alist)
519 (list (list ? "default"))))
521 r1 r2 ass
523 ;; read in the type to use
524 (export-plist
525 (progn
526 (save-excursion
527 (save-window-excursion
528 (delete-other-windows)
529 (with-output-to-temp-buffer "*Org Export/Generic Styles Help*"
530 (princ help))
531 (org-fit-window-to-buffer (get-buffer-window
532 "*Org Export/Generic Styles Help*"))
533 (message "Select command: ")
534 (setq r1 (read-char-exclusive))))
535 (setq r2 (if (< r1 27) (+ r1 96) r1))
536 (unless (setq ass (cadr (assq r2 cmds)))
537 (error "No command associated with key %c" r1))
539 (cdr (assoc
540 (if (equal ass "default") org-generic-export-type ass)
541 org-generic-alist))))
543 (custom-times org-display-custom-times)
544 (org-generic-current-indentation '(0 . 0))
545 (level 0) (old-level 0) line txt lastwastext
546 (umax nil)
547 (umax-toc nil)
548 (case-fold-search nil)
549 (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
550 (filesuffix (or (plist-get export-plist :file-suffix) ".foo"))
551 (filename (concat (file-name-as-directory
552 (org-export-directory :ascii opt-plist))
553 (file-name-sans-extension
554 (or (and subtree-p
555 (org-entry-get (region-beginning)
556 "EXPORT_FILE_NAME" t))
557 (file-name-nondirectory bfname)))
558 filesuffix))
559 (filename (if (equal (file-truename filename)
560 (file-truename bfname))
561 (concat filename filesuffix)
562 filename))
563 (buffer (find-file-noselect filename))
564 (org-levels-open (make-vector org-level-max nil))
565 (odd org-odd-levels-only)
566 (date (plist-get opt-plist :date))
567 (author (plist-get opt-plist :author))
568 (title (or (and subtree-p (org-export-get-title-from-subtree))
569 (plist-get opt-plist :title)
570 (and (not
571 (plist-get opt-plist :skip-before-1st-heading))
572 (org-export-grab-title-from-buffer))
573 (file-name-sans-extension
574 (file-name-nondirectory bfname))))
575 (email (plist-get opt-plist :email))
576 (language (plist-get opt-plist :language))
577 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
578 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
579 (todo nil)
580 (lang-words nil)
581 (region
582 (buffer-substring
583 (if (org-region-active-p) (region-beginning) (point-min))
584 (if (org-region-active-p) (region-end) (point-max))))
585 (lines (org-split-string
586 (org-export-preprocess-string
587 region
588 :for-ascii t
589 :skip-before-1st-heading
590 (plist-get opt-plist :skip-before-1st-heading)
591 :drawers (plist-get export-plist :drawers-export)
592 :tags (plist-get export-plist :tags-export)
593 :priority (plist-get export-plist :priority-export)
594 :footnotes (plist-get export-plist :footnotes-export)
595 :timestamps (plist-get export-plist :timestamps-export)
596 :todo-keywords (plist-get export-plist :todo-keywords-export)
597 :verbatim-multiline t
598 :select-tags (plist-get export-plist :select-tags-export)
599 :exclude-tags (plist-get export-plist :exclude-tags-export)
600 :archived-trees
601 (plist-get export-plist :archived-trees-export)
602 :add-text (plist-get opt-plist :text))
603 "\n"))
604 ;; export-generic plist variables
605 (withtags (plist-get export-plist :tags-export))
606 (tagsintoc (plist-get export-plist :toc-tags-export))
607 (tocnotagsstr (or (plist-get export-plist :toc-tags-none-string) ""))
608 (tocdepth (plist-get export-plist :toc-indent-depth))
609 (tocindentchar (plist-get export-plist :toc-indent-char))
610 (tocsecnums (plist-get export-plist :toc-section-numbers))
611 (tocsecnumform (plist-get export-plist :toc-section-number-format))
612 (tocformat (plist-get export-plist :toc-format))
613 (tocformtodo (plist-get export-plist :toc-format-with-todo))
614 (tocprefix (plist-get export-plist :toc-prefix))
615 (tocsuffix (plist-get export-plist :toc-suffix))
616 (bodyfixedpre (plist-get export-plist :body-line-fixed-prefix))
617 (bodyfixedsuf (plist-get export-plist :body-line-fixed-suffix))
618 (bodyfixedform (or (plist-get export-plist :body-line-fixed-format)
619 "%s"))
620 (listprefix (plist-get export-plist :body-list-prefix))
621 (listsuffix (plist-get export-plist :body-list-suffix))
622 (listformat (or (plist-get export-plist :body-list-format) "%s\n"))
623 (numlistleavenum
624 (plist-get export-plist :body-number-list-leave-number))
625 (numlistprefix (plist-get export-plist :body-number-list-prefix))
626 (numlistsuffix (plist-get export-plist :body-number-list-suffix))
627 (numlistformat
628 (or (plist-get export-plist :body-number-list-format) "%s\n"))
629 (listchecktodo
630 (or (plist-get export-plist :body-list-checkbox-todo) "\\1"))
631 (listcheckdone
632 (or (plist-get export-plist :body-list-checkbox-done) "\\1"))
633 (listcheckhalf
634 (or (plist-get export-plist :body-list-checkbox-half) "\\1"))
635 (listchecktodoend
636 (or (plist-get export-plist :body-list-checkbox-todo-end) ""))
637 (listcheckdoneend
638 (or (plist-get export-plist :body-list-checkbox-done-end) ""))
639 (listcheckhalfend
640 (or (plist-get export-plist :body-list-checkbox-half-end) ""))
641 (bodytextpre (plist-get export-plist :body-text-prefix))
642 (bodytextsuf (plist-get export-plist :body-text-suffix))
643 (bodylinewrap (plist-get export-plist :body-line-wrap))
644 (bodylineform (or (plist-get export-plist :body-line-format) "%s"))
646 thetoc toctags have-headings first-heading-pos
647 table-open table-buffer link-buffer link desc desc0 rpl wrap)
649 (let ((inhibit-read-only t))
650 (org-unmodified
651 (remove-text-properties (point-min) (point-max)
652 '(:org-license-to-kill t))))
654 (setq org-min-level (org-get-min-level lines level-offset))
655 (setq org-last-level org-min-level)
656 (org-init-section-numbers)
658 (find-file-noselect filename)
660 (setq lang-words (or (assoc language org-export-language-setup)
661 (assoc "en" org-export-language-setup)))
662 (switch-to-buffer-other-window buffer)
663 (erase-buffer)
664 (fundamental-mode)
665 ;; create local variables for all options, to make sure all called
666 ;; functions get the correct information
667 (mapc (lambda (x)
668 (set (make-local-variable (nth 2 x))
669 (plist-get opt-plist (car x))))
670 org-export-plist-vars)
671 (org-set-local 'org-odd-levels-only odd)
672 (setq umax (if arg (prefix-numeric-value arg)
673 org-export-headline-levels))
674 (setq umax-toc umax)
676 ;; File header
677 (if title
678 (insert
679 (org-export-generic-header title export-plist
680 :title-prefix
681 :title-format
682 :title-suffix)))
684 (if (and (or author email)
685 (plist-get export-plist :author-export))
686 (insert (concat (nth 1 lang-words) ": " (or author "")
687 (if email (concat " <" email ">") "")
688 "\n")))
690 (cond
691 ((and date (string-match "%" date))
692 (setq date (format-time-string date)))
693 (date)
694 (t (setq date (format-time-string "%Y-%m-%d %T %Z"))))
696 (if (and date (plist-get export-plist :date-export))
697 (insert
698 (org-export-generic-header date export-plist
699 :date-prefix
700 :date-format
701 :date-suffix)))
703 ;; export the table of contents first
704 (if (plist-get export-plist :toc-export)
705 (progn
706 (push
707 (org-export-generic-header (nth 3 lang-words) export-plist
708 :toc-header-prefix
709 :toc-header-format
710 :toc-header-suffix)
711 thetoc)
713 (if tocprefix
714 (push tocprefix thetoc))
716 (mapc '(lambda (line)
717 (if (string-match org-todo-line-regexp line)
718 ;; This is a headline
719 (progn
720 (setq have-headings t)
721 (setq level (- (match-end 1) (match-beginning 1)
722 level-offset)
723 level (org-tr-level level)
724 txt (match-string 3 line)
725 todo
726 (or (and org-export-mark-todo-in-toc
727 (match-beginning 2)
728 (not (member (match-string 2 line)
729 org-done-keywords)))
730 ; TODO, not DONE
731 (and org-export-mark-todo-in-toc
732 (= level umax-toc)
733 (org-search-todo-below
734 line lines level))))
735 (setq txt (org-html-expand-for-generic txt))
737 (while (string-match org-bracket-link-regexp txt)
738 (setq txt
739 (replace-match
740 (match-string (if (match-end 2) 3 1) txt)
741 t t txt)))
743 (if (and (not tagsintoc)
744 (string-match
745 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
746 txt))
747 (setq txt (replace-match "" t t txt))
748 ; include tags but formated
749 (if (string-match
750 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$")
751 txt)
752 (progn
753 (setq
754 toctags
755 (org-export-generic-header
756 (match-string 1 txt)
757 export-plist :toc-tags-prefix
758 :toc-tags-format :toc-tags-suffix))
759 (string-match
760 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
761 txt)
762 (setq txt (replace-match "" t t txt)))
763 (setq toctags tocnotagsstr)))
765 (if (string-match quote-re0 txt)
766 (setq txt (replace-match "" t t txt)))
768 (if (<= level umax-toc)
769 (progn
770 (push
771 (concat
773 (make-string
774 (* (max 0 (- level org-min-level)) tocdepth)
775 tocindentchar)
777 (if tocsecnums
778 (format tocsecnumform
779 (org-section-number level))
782 (format
783 (if todo tocformtodo tocformat)
784 txt)
786 toctags)
788 thetoc)
789 (setq org-last-level level))
790 ))))
791 lines)
792 (if tocsuffix
793 (push tocsuffix thetoc))
794 (setq thetoc (if have-headings (nreverse thetoc) nil))))
796 (org-init-section-numbers)
797 (org-export-generic-check-section "top")
798 (while (setq line (pop lines))
799 (when (and link-buffer (string-match "^\\*+ " line))
800 (org-export-generic-push-links (nreverse link-buffer))
801 (setq link-buffer nil))
802 (setq wrap nil)
803 ;; Remove the quoted HTML tags.
804 ;; XXX
805 (setq line (org-html-expand-for-generic line))
806 ;; Replace links with the description when possible
807 ;; XXX
808 (while (string-match org-bracket-link-regexp line)
809 (setq link (match-string 1 line)
810 desc0 (match-string 3 line)
811 desc (or desc0 (match-string 1 line)))
812 (if (and (> (length link) 8)
813 (equal (substring link 0 8) "coderef:"))
814 (setq line (replace-match
815 (format (org-export-get-coderef-format (substring link 8) desc)
816 (cdr (assoc
817 (substring link 8)
818 org-export-code-refs)))
819 t t line))
820 (setq rpl (concat "["
821 (or (match-string 3 line) (match-string 1 line))
822 "]"))
823 (when (and desc0 (not (equal desc0 link)))
824 (if org-export-generic-links-to-notes
825 (push (cons desc0 link) link-buffer)
826 (setq rpl (concat rpl " (" link ")")
827 wrap (+ (length line) (- (length (match-string 0) line))
828 (length desc)))))
829 (setq line (replace-match rpl t t line))))
830 (when custom-times
831 (setq line (org-translate-time line)))
832 (cond
833 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
835 ;; a Headline
837 (org-export-generic-check-section "headline")
839 (setq first-heading-pos (or first-heading-pos (point)))
840 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)
841 level-offset))
842 txt (match-string 2 line))
843 (org-generic-level-start level old-level txt umax export-plist lines)
844 (setq old-level level))
846 ((and org-export-with-tables
847 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
849 ;; a Table
851 (org-export-generic-check-section "table")
853 (if (not table-open)
854 ;; New table starts
855 (setq table-open t table-buffer nil))
856 ;; Accumulate table lines
857 (setq table-buffer (cons line table-buffer))
858 (when (or (not lines)
859 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
860 (car lines))))
861 (setq table-open nil
862 table-buffer (nreverse table-buffer))
863 (insert (mapconcat
864 (lambda (x)
865 (org-fix-indentation x org-generic-current-indentation))
866 (org-format-table-generic table-buffer)
867 "\n") "\n")))
869 ((string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)
871 ;; pre-formated text
873 (setq line (replace-match "\\1" nil nil line))
875 (org-export-generic-check-section "preformat" bodyfixedpre bodyfixedsuf)
877 (insert (format bodyfixedform line)))
879 ((or (string-match "^\\([ \t]*\\)\\([\-\+][ \t]*\\)" line)
880 ;; if the bullet list item is an asterisk, the leading space is /mandatory/
881 ;; [2010/02/02:rpg]
882 (string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
884 ;; plain list item
886 ;; TODO: nested lists
888 ;; I believe this gets rid of leading whitespace.
889 (setq line (replace-match "" nil nil line))
891 ;; won't this insert the suffix /before/ the last line of the list?
892 ;; also isn't it spoofed by bulleted lists that have a line skip between the list items
893 ;; unless 'org-empty-line-terminates-plain-lists' is true?
894 (org-export-generic-check-section "liststart" listprefix listsuffix)
896 ;; deal with checkboxes
897 (cond
898 ((string-match "^\\(\\[ \\]\\)[ \t]*" line)
899 (setq line (concat (replace-match listchecktodo nil nil line)
900 listchecktodoend)))
901 ((string-match "^\\(\\[X\\]\\)[ \t]*" line)
902 (setq line (concat (replace-match listcheckdone nil nil line)
903 listcheckdoneend)))
904 ((string-match "^\\(\\[/\\]\\)[ \t]*" line)
905 (setq line (concat (replace-match listcheckhalf nil nil line)
906 listcheckhalfend)))
909 (insert (format listformat line)))
910 ((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
912 ;; numbered list item
914 ;; TODO: nested lists
916 (setq line (replace-match (if numlistleavenum "\\2" "") nil nil line))
918 (org-export-generic-check-section "numliststart"
919 numlistprefix numlistsuffix)
921 ;; deal with checkboxes
922 ;; TODO: whoops; leaving the numbers is a problem for ^ matching
923 (cond
924 ((string-match "\\(\\[ \\]\\)[ \t]*" line)
925 (setq line (concat (replace-match listchecktodo nil nil line)
926 listchecktodoend)))
927 ((string-match "\\(\\[X\\]\\)[ \t]*" line)
928 (setq line (concat (replace-match listcheckdone nil nil line)
929 listcheckdoneend)))
930 ((string-match "\\(\\[/\\]\\)[ \t]*" line)
931 (setq line (concat (replace-match listcheckhalf nil nil line)
932 listcheckhalfend)))
935 (insert (format numlistformat line)))
938 ;; body
940 (org-export-generic-check-section "body" bodytextpre bodytextsuf)
942 ;; XXX: properties? list?
943 (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
944 (setq line (replace-match "\\1\\3:" t nil line)))
946 (setq line (org-fix-indentation line org-generic-current-indentation))
948 ;; Remove forced line breaks
949 (if (string-match "\\\\\\\\[ \t]*$" line)
950 (setq line (replace-match "" t t line)))
952 (if bodylinewrap
953 ;; XXX: was dependent on wrap var which was calculated by???
954 (if (> (length line) bodylinewrap)
955 (setq line
956 (org-export-generic-wrap line bodylinewrap))
957 (setq line line)))
958 (insert (format bodylineform line)))))
960 ;; if we're at a level > 0; insert the closing body level stuff
961 (let ((counter 0))
962 (while (> (- level counter) 0)
963 (insert
964 (org-export-generic-format export-plist :body-section-suffix 0
965 (- level counter)))
966 (setq counter (1+ counter))))
968 (org-export-generic-check-section "bottom")
970 (org-export-generic-push-links (nreverse link-buffer))
972 (normal-mode)
974 ;; insert the table of contents
975 (when thetoc
976 (goto-char (point-min))
977 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
978 (progn
979 (goto-char (match-beginning 0))
980 (replace-match ""))
981 (goto-char first-heading-pos))
982 (mapc 'insert thetoc)
983 (or (looking-at "[ \t]*\n[ \t]*\n")
984 (insert "\n\n")))
986 ;; Convert whitespace place holders
987 (goto-char (point-min))
988 (let (beg end)
989 (while (setq beg (next-single-property-change (point) 'org-whitespace))
990 (setq end (next-single-property-change beg 'org-whitespace))
991 (goto-char beg)
992 (delete-region beg end)
993 (insert (make-string (- end beg) ?\ ))))
995 (save-buffer)
997 ;; remove display and invisible chars
998 (let (beg end)
999 (goto-char (point-min))
1000 (while (setq beg (next-single-property-change (point) 'display))
1001 (setq end (next-single-property-change beg 'display))
1002 (delete-region beg end)
1003 (goto-char beg)
1004 (insert "=>"))
1005 (goto-char (point-min))
1006 (while (setq beg (next-single-property-change (point) 'org-cwidth))
1007 (setq end (next-single-property-change beg 'org-cwidth))
1008 (delete-region beg end)
1009 (goto-char beg)))
1010 (goto-char (point-min))))
1012 (defun org-export-generic-format (export-plist prop &optional len n reverse)
1013 "converts a property specification to a string given types of properties
1015 The EXPORT-PLIST should be defined as the lookup plist.
1016 The PROP should be the property name to search for in it.
1017 LEN is set to the length of multi-characters strings to generate (or 0)
1018 N is the tree depth
1019 REVERSE means to reverse the list if the plist match is a list
1021 (let* ((prefixtype (plist-get export-plist prop))
1022 subtype)
1023 (cond
1024 ((null prefixtype) "")
1025 ((and len (char-or-string-p prefixtype) (not (stringp prefixtype)))
1026 ;; sequence of chars
1027 (concat (make-string len prefixtype) "\n"))
1028 ((stringp prefixtype)
1029 prefixtype)
1030 ((and n (listp prefixtype))
1031 (if reverse
1032 (setq prefixtype (reverse prefixtype)))
1033 (setq subtype (if (> n (length prefixtype))
1034 (car (last prefixtype))
1035 (nth (1- n) prefixtype)))
1036 (if (stringp subtype)
1037 subtype
1038 (concat (make-string len subtype) "\n")))
1039 (t ""))
1042 (defun org-export-generic-header (header export-plist
1043 prefixprop formatprop postfixprop
1044 &optional n reverse)
1045 "convert a header to an output string given formatting property names"
1046 (let* ((formatspec (plist-get export-plist formatprop))
1047 (len (length header)))
1048 (concat
1049 (org-export-generic-format export-plist prefixprop len n reverse)
1050 (format (or formatspec "%s") header)
1051 (org-export-generic-format export-plist postfixprop len n reverse))
1054 (defun org-export-generic-preprocess (parameters)
1055 "Do extra work for ASCII export"
1056 ;; Put quotes around verbatim text
1057 (goto-char (point-min))
1058 (while (re-search-forward org-verbatim-re nil t)
1059 (goto-char (match-end 2))
1060 (backward-delete-char 1) (insert "'")
1061 (goto-char (match-beginning 2))
1062 (delete-char 1) (insert "`")
1063 (goto-char (match-end 2)))
1064 ;; Remove target markers
1065 (goto-char (point-min))
1066 (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t)
1067 (replace-match "\\1\\2")))
1069 (defun org-html-expand-for-generic (line)
1070 "Handle quoted HTML for ASCII export."
1071 (if org-export-html-expand
1072 (while (string-match "@<[^<>\n]*>" line)
1073 ;; We just remove the tags for now.
1074 (setq line (replace-match "" nil nil line))))
1075 line)
1077 (defun org-export-generic-wrap (line where)
1078 "Wrap LINE at or before WHERE."
1079 (let* ((ind (org-get-indentation line))
1080 (indstr (make-string ind ?\ ))
1081 (len (length line))
1082 (result "")
1083 pos didfirst)
1084 (while (> len where)
1085 (catch 'found
1086 (loop for i from where downto (/ where 2) do
1087 (and (equal (aref line i) ?\ )
1088 (setq pos i)
1089 (throw 'found t))))
1090 (if pos
1091 (progn
1092 (setq result
1093 (concat result
1094 (if didfirst indstr "")
1095 (substring line 0 pos)
1096 "\n"))
1097 (setq didfirst t)
1098 (setq line (substring line (1+ pos)))
1099 (setq len (length line)))
1100 (setq result (concat result line))
1101 (setq len 0)))
1102 (concat result indstr line)))
1104 (defun org-export-generic-push-links (link-buffer)
1105 "Push out links in the buffer."
1106 (when link-buffer
1107 ;; We still have links to push out.
1108 (insert "\n")
1109 (let ((ind ""))
1110 (save-match-data
1111 (if (save-excursion
1112 (re-search-backward
1113 "^\\(\\([ \t]*\\)\\|\\(\\*+ \\)\\)[^ \t\n]" nil t))
1114 (setq ind (or (match-string 2)
1115 (make-string (length (match-string 3)) ?\ )))))
1116 (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n"))
1117 link-buffer))
1118 (insert "\n")))
1120 (defun org-generic-level-start (level old-level title umax export-plist
1121 &optional lines)
1122 "Insert a new level in a generic export."
1123 (let ((n (- level umax 1))
1124 (ind 0)
1125 (diff (- level old-level)) (counter 0)
1126 (secnums (plist-get export-plist :body-header-section-numbers))
1127 (secnumformat
1128 (plist-get export-plist :body-header-section-number-format))
1129 char tagstring)
1130 (unless org-export-with-tags
1131 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
1132 (setq title (replace-match "" t t title))))
1134 (cond
1135 ;; going deeper
1136 ((> level old-level)
1137 (while (< (+ old-level counter) (1- level))
1138 (insert
1139 (org-export-generic-format export-plist :body-section-prefix 0
1140 (+ old-level counter)))
1141 (setq counter (1+ counter))
1143 ;; going up
1144 ((< level old-level)
1145 (while (> (- old-level counter) (1- level))
1146 (insert
1147 (org-export-generic-format export-plist :body-section-suffix 0
1148 (- old-level counter)))
1149 (setq counter (1+ counter))
1151 ;; same level
1152 ((= level old-level)
1153 (insert
1154 (org-export-generic-format export-plist :body-section-suffix 0 level))
1157 (insert
1158 (org-export-generic-format export-plist :body-section-prefix 0 level))
1160 (if (and org-export-with-section-numbers
1161 secnums
1162 (or (not (numberp secnums))
1163 (< level secnums)))
1164 (setq title
1165 (concat (format (or secnumformat "%s ")
1166 (org-section-number level)) title)))
1168 ;; handle tags and formatting
1169 (if (string-match
1170 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") title)
1171 (progn
1172 (if (plist-get export-plist :body-tags-export)
1173 (setq tagstring (org-export-generic-header (match-string 1 title)
1174 export-plist
1175 :body-tags-prefix
1176 :body-tags-format
1177 :body-tags-suffix)))
1178 (string-match (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$") title)
1179 (setq title (replace-match "" t t title)))
1180 (setq tagstring (plist-get export-plist :body-tags-none-string)))
1182 (insert
1183 (org-export-generic-header title export-plist
1184 :body-section-header-prefix
1185 :body-section-header-format
1186 :body-section-header-suffix
1187 level))
1188 (if tagstring
1189 (insert tagstring))
1191 (setq org-generic-current-indentation '(0 . 0))))
1193 (defun org-insert-centered (s &optional underline)
1194 "Insert the string S centered and underline it with character UNDERLINE."
1195 (let ((ind (max (/ (- fill-column (string-width s)) 2) 0)))
1196 (insert (make-string ind ?\ ) s "\n")
1197 (if underline
1198 (insert (make-string ind ?\ )
1199 (make-string (string-width s) underline)
1200 "\n"))))
1202 (defvar org-table-colgroup-info nil)
1203 (defun org-format-table-generic (lines)
1204 "Format a table for ascii export."
1205 (if (stringp lines)
1206 (setq lines (org-split-string lines "\n")))
1207 (if (not (string-match "^[ \t]*|" (car lines)))
1208 ;; Table made by table.el - test for spanning
1209 lines
1211 ;; A normal org table
1212 ;; Get rid of hlines at beginning and end
1213 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1214 (setq lines (nreverse lines))
1215 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1216 (setq lines (nreverse lines))
1217 (when org-export-table-remove-special-lines
1218 ;; Check if the table has a marking column. If yes remove the
1219 ;; column and the special lines
1220 (setq lines (org-table-clean-before-export lines)))
1221 ;; Get rid of the vertical lines except for grouping
1222 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
1223 rtn line vl1 start)
1224 (while (setq line (pop lines))
1225 (if (string-match org-table-hline-regexp line)
1226 (and (string-match "|\\(.*\\)|" line)
1227 (setq line (replace-match " \\1" t nil line)))
1228 (setq start 0 vl1 vl)
1229 (while (string-match "|" line start)
1230 (setq start (match-end 0))
1231 (or (pop vl1) (setq line (replace-match " " t t line)))))
1232 (push line rtn))
1233 (nreverse rtn))))
1235 (defun org-colgroup-info-to-vline-list (info)
1236 (let (vl new last)
1237 (while info
1238 (setq last new new (pop info))
1239 (if (or (memq last '(:end :startend))
1240 (memq new '(:start :startend)))
1241 (push t vl)
1242 (push nil vl)))
1243 (setq vl (nreverse vl))
1244 (and vl (setcar vl nil))
1245 vl))
1247 (provide 'org-generic)
1248 (provide 'org-export-generic)
1250 ;;; org-export-generic.el ends here