contrib/lisp: don't use `outline-regexp'.
[org-mode/org-kjn.git] / contrib / lisp / org-export-generic.el
blob4be0a20d2090d3bc45e5f58007ae2baa2edeea8b
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
93 ;; * fonts: at least monospace is not handled at all here.
95 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
97 ;;; Commentary:
99 (require 'org-exp)
100 (require 'assoc)
102 (defgroup org-export-generic nil
103 "Options specific for ASCII export of Org-mode files."
104 :tag "Org Export ASCII"
105 :group 'org-export)
107 (defcustom org-export-generic-links-to-notes t
108 "Non-nil means convert links to notes before the next headline.
109 When nil, the link will be exported in place. If the line becomes long
110 in this way, it will be wrapped."
111 :group 'org-export-generic
112 :type 'boolean)
115 (defvar org-generic-current-indentation nil) ; For communication
117 (defvar org-generic-alist
120 ;; generic DEMO exporter
122 ;; (this tries to use every specifier for demo purposes)
124 ("demo"
125 :file-suffix ".txt"
126 :key-binding ?d
128 :header-prefix "<header>\n"
129 :header-suffix "</header>\n"
131 :author-export t
132 :tags-export t
134 :drawers-export t
137 :title-prefix ?=
138 :title-format "<h1>%s</h1>\n"
139 :title-suffix ?=
141 :date-export t
142 :date-prefix "<date>"
143 :date-format "<br /><b>Date:</b> <i>%s</i><br />"
144 :date-suffix "</date>\n\n"
146 :toc-export t
147 :toc-header-prefix "<tocname>\n"
148 :toc-header-format "__%s__\n"
149 :toc-header-suffix "</tocname>\n"
151 :toc-prefix "<toc>\n"
152 :toc-suffix "</toc>\n"
154 :toc-section-numbers t
155 :toc-section-number-format "\#(%s) "
156 :toc-format "--%s--"
157 :toc-format-with-todo "!!%s!!\n"
158 :toc-indent-char ?\
159 :toc-indent-depth 4
161 :toc-tags-export t
162 :toc-tags-prefix " <tags>"
163 :toc-tags-format "*%s*"
164 :toc-tags-suffix "</tags>\n"
165 :toc-tags-none-string "\n"
167 :body-header-section-numbers 3 ; t = all, nil = none
169 ; lists indicate different things per level
170 ; list contents or straight value can either be a
171 ; ?x char reference for printing strings that match the header len
172 ; "" string to print directly
173 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
174 "<h4>" "<h5>" "<h6>")
175 :body-section-header-format "%s"
176 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
177 "</h4>\n" "</h5>\n" "</h6>\n")
179 :timestamps-export t
180 :priorities-export t
181 :todo-keywords-export t
183 :body-tags-export t
184 :body-tags-prefix " <tags>"
185 :body-tags-suffix "</tags>\n"
187 ; section prefixes/suffixes can be direct strings or lists as well
188 :body-section-prefix "<secprefix>\n"
189 :body-section-suffix "</secsuffix>\n"
190 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
191 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
194 ; if preformated text should be included (eg, : prefixed)
195 :body-line-export-preformated t
196 :body-line-fixed-prefix "<pre>\n"
197 :body-line-fixed-suffix "\n</pre>\n"
198 :body-line-fixed-format "%s\n"
201 :body-list-prefix "<list>\n"
202 :body-list-suffix "</list>\n"
203 :body-list-format "<li>%s</li>\n"
205 :body-number-list-prefix "<ol>\n"
206 :body-number-list-suffix "</ol>\n"
207 :body-number-list-format "<li>%s</li>\n"
208 :body-number-list-leave-number t
210 :body-list-checkbox-todo "<checkbox type=\"todo\">"
211 :body-list-checkbox-todo-end "</checkbox (todo)>"
212 :body-list-checkbox-done "<checkbox type=\"done\">"
213 :body-list-checkbox-done-end "</checkbox (done)>"
214 :body-list-checkbox-half "<checkbox type=\"half\">"
215 :body-list-checkbox-half-end "</checkbox (half)>"
220 ; other body lines
221 :body-line-format "%s"
222 :body-line-wrap 60 ; wrap at 60 chars
224 ; print above and below all body parts
225 :body-text-prefix "<p>\n"
226 :body-text-suffix "</p>\n"
231 ;; ascii exporter
233 ;; (close to the original ascii specifier)
235 ("ascii"
236 :file-suffix ".txt"
237 :key-binding ?a
239 :header-prefix ""
240 :header-suffix ""
242 :title-prefix ?=
243 :title-format "%s\n"
244 :title-suffix ?=
246 :date-export t
247 :date-prefix ""
248 :date-format "Date: %s\n"
249 :date-suffix ""
251 :toc-header-prefix ""
252 :toc-header-format "%s\n"
253 :toc-header-suffix ?=
255 :toc-export t
256 :toc-section-numbers t
257 :toc-section-number-format "%s "
258 :toc-format "%s\n"
259 :toc-format-with-todo "%s (*)\n"
260 :toc-indent-char ?\
261 :toc-indent-depth 4
263 :body-header-section-numbers 3
264 :body-section-prefix "\n"
266 ; :body-section-header-prefix "\n"
267 ; :body-section-header-format "%s\n"
268 ; :body-section-header-suffix (?\$ ?\# ?^ ?\~ ?\= ?\-)
270 :body-section-header-prefix ("" "" "" "* " " + " " - ")
271 :body-section-header-format "%s\n"
272 :body-section-header-suffix (?~ ?= ?- "\n" "\n" "\n")
274 ; :body-section-marker-prefix ""
275 ; :body-section-marker-chars (?\$ ?\# ?^ ?\~ ?\= ?\-)
276 ; :body-section-marker-suffix "\n"
278 :body-line-export-preformated t
279 :body-line-format "%s\n"
280 :body-line-wrap 75
282 ; :body-text-prefix "<t>\n"
283 ; :body-text-suffix "</t>\n"
286 :body-bullet-list-prefix (?* ?+ ?-)
287 ; :body-bullet-list-suffix (?* ?+ ?-)
291 ;; wikipedia
293 ("wikipedia"
294 :file-suffix ".txt"
295 :key-binding ?w
297 :header-prefix ""
298 :header-suffix ""
300 :title-format "= %s =\n"
302 :date-export nil
304 :toc-export nil
306 :body-header-section-numbers nil
307 :body-section-prefix "\n"
309 :body-section-header-prefix ("= " "== " "=== "
310 "==== " "===== " "====== ")
311 :body-section-header-suffix (" =\n\n" " ==\n\n" " ===\n\n"
312 " ====\n\n" " =====\n\n" " ======\n\n")
314 :body-line-export-preformated t ;; yes/no/maybe???
315 :body-line-format "%s\n"
316 :body-line-wrap 75
318 :body-line-fixed-format " %s\n"
320 :body-list-format "* %s\n"
321 :body-number-list-format "# %s\n"
323 :body-bullet-list-prefix ("* " "** " "*** " "**** " "***** ")
327 ;; minimal html exporter
329 ("html"
330 ;; simple html output
331 :file-suffix ".html"
332 :key-binding ?h
334 :header-prefix "<body>"
336 :title-format "<h1>%s</h1>\n\n"
338 :date-export t
339 :date-format "<br /><b>Date:</b> <i>%s</i><br />\n\n"
341 :toc-export nil
343 :body-header-section-numbers 3
345 :body-section-header-prefix ("<h1>" "<h2>" "<h3>"
346 "<h4>" "<h5>" "<h6>")
347 :body-section-header-format "%s"
348 :body-section-header-suffix ("</h1>\n" "</h2>\n" "</h3>\n"
349 "</h4>\n" "</h5>\n" "</h6>\n")
351 :body-section-prefix "<secprefix>\n"
352 :body-section-suffix "</secsuffix>\n"
353 ; :body-section-prefix ("<sec1>\n" "<sec2>\n" "<sec3>\n")
354 ; :body-section-suffix ("</sec1>\n" "</sec2>\n" "</sec3>\n")
356 :body-line-export-preformated t
357 :body-line-format "%s\n"
359 :body-text-prefix "<p>\n"
360 :body-text-suffix "</p>\n"
362 :body-bullet-list-prefix (?* ?+ ?-)
363 ; :body-bullet-list-suffix (?* ?+ ?-)
367 ;; internet-draft .xml for xml2rfc exporter
369 ("ietfid"
370 ;; this tries to use every specifier for demo purposes
371 :file-suffix ".xml"
372 :key-binding ?i
374 :title-prefix "<?xml version=\"1.0\"\?>
375 <!DOCTYPE rfc SYSTEM \"rfc2629.dtd\" [
376 <!ENTITY rfcs PUBLIC '' 'blah'>
377 <?rfc strict=\"yes\" ?>
378 <?rfc toc=\"yes\" ?>
379 <?rfc tocdepth=\"4\" ?>
380 <?rfc symrefs=\"yes\" ?>
381 <?rfc compact=\"yes\" ?>
382 <?rfc subcompact=\"no\" ?>
383 <rfc category=\"std\" ipr=\"pre5378Trust200902\" docName=\"FILLME.txt\">
384 <front>
386 :title-format "<title abbrev=\"ABBREV HERE\">\n%s\n</title>\n"
387 :title-suffix "<author initials=\"A.A\" surname=\"LASTNAME\" fullname=\"FULL NAME\">
388 <organization>Comany, Inc..</organization>
389 <address>
390 <postal>
391 <street></street>
392 <city></city>
393 <region></region>
394 <code></code>
395 <country></country>
396 </postal>
397 <phone></phone>
398 <email></email>
399 </address>
400 </author>
401 <date month=\"FILLMONTH\" year=\"FILLYEAR\"/>
402 <area>Operations and Management</area>
403 <workgroup>FIXME</workgroup>
404 <abstract>\n"
405 :date-export nil
407 :toc-export nil
409 :body-header-section-numbers nil
411 :body-section-header-format "<section title=\"%s\">\n"
412 :body-section-suffix "</section>\n"
414 ; if preformated text should be included (eg, : prefixed)
415 :body-line-export-preformated t
416 :body-line-fixed-prefix "<figure>\n<artwork>\n"
417 :body-line-fixed-suffix "\n</artwork>\n</figure>\n"
419 ; other body lines
420 :body-line-format "%s"
421 :body-line-wrap 75
423 ; print above and below all body parts
424 :body-text-prefix "<t>\n"
425 :body-text-suffix "</t>\n"
427 :body-list-prefix "<list style=\"symbols\">\n"
428 :body-list-suffix "</list>\n"
429 :body-list-format "<t>%s</t>\n"
433 "A assoc list of property lists to specify export definitions"
436 (setq org-generic-export-type "demo")
438 (defvar org-export-generic-section-type "")
439 (defvar org-export-generic-section-suffix "")
441 ;;;###autoload
442 (defun org-set-generic-type (type definition)
443 "Adds a TYPE and DEFINITION to the existing list of defined generic
444 export definitions."
445 (aput 'org-generic-alist type definition))
447 ;;; helper functions for org-set-generic-type
448 (defvar org-export-generic-keywords nil)
449 (defmacro* def-org-export-generic-keyword (keyword
450 &key documentation
451 type)
452 "Define KEYWORD as a legitimate element for inclusion in
453 the body of an org-set-generic-type definition."
454 `(progn
455 (pushnew ,keyword org-export-generic-keywords)
456 ;; TODO: push the documentation and type information
457 ;; somewhere where it will do us some good.
460 (def-org-export-generic-keyword :body-newline-paragraph
461 :documentation "Bound either to NIL or to a pattern to be
462 inserted in the output for every blank line in the input.
463 The intention is to handle formats where text is flowed, and
464 newlines are interpreted as significant \(e.g., as indicating
465 preformatted text\). A common non-nil value for this keyword
466 is \"\\n\". Should typically be combined with a value for
467 :body-line-format that does NOT end with a newline."
468 :type string)
470 ;;; fontification keywords
471 (def-org-export-generic-keyword :bold-format)
472 (def-org-export-generic-keyword :italic-format)
473 (def-org-export-generic-keyword :underline-format)
474 (def-org-export-generic-keyword :strikethrough-format)
475 (def-org-export-generic-keyword :code-format)
476 (def-org-export-generic-keyword :verbatim-format)
481 (defun org-export-generic-remember-section (type suffix &optional prefix)
482 (setq org-export-generic-section-type type)
483 (setq org-export-generic-section-suffix suffix)
484 (if prefix
485 (insert prefix))
488 (defun org-export-generic-check-section (type &optional prefix suffix)
489 "checks to see if type is already in use, or we're switching parts
490 If we're switching, then insert a potentially previously remembered
491 suffix, and insert the current prefix immediately and then save the
492 suffix a later change time."
494 (when (not (equal type org-export-generic-section-type))
495 (if org-export-generic-section-suffix
496 (insert org-export-generic-section-suffix))
497 (setq org-export-generic-section-type type)
498 (setq org-export-generic-section-suffix suffix)
499 (if prefix
500 (insert prefix))))
502 ;;;###autoload
503 (defun org-export-generic (arg)
504 "Export the outline as generic output.
505 If there is an active region, export only the region.
506 The prefix ARG specifies how many levels of the outline should become
507 underlined headlines. The default is 3."
508 (interactive "P")
509 (setq-default org-todo-line-regexp org-todo-line-regexp)
510 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
511 (org-infile-export-plist)))
512 (region-p (org-region-active-p))
513 (rbeg (and region-p (region-beginning)))
514 (rend (and region-p (region-end)))
515 (subtree-p
516 (when region-p
517 (save-excursion
518 (goto-char rbeg)
519 (and (org-at-heading-p)
520 (>= (org-end-of-subtree t t) rend)))))
521 (level-offset (if subtree-p
522 (save-excursion
523 (goto-char rbeg)
524 (+ (funcall outline-level)
525 (if org-odd-levels-only 1 0)))
527 (opt-plist (setq org-export-opt-plist
528 (if subtree-p
529 (org-export-add-subtree-options opt-plist rbeg)
530 opt-plist)))
532 helpstart
533 (bogus (mapc (lambda (x)
534 (setq helpstart
535 (concat helpstart "\["
536 (char-to-string
537 (plist-get (cdr x) :key-binding))
538 "] " (car x) "\n")))
539 org-generic-alist))
541 (help (concat helpstart "
543 \[ ] the current setting of the org-generic-export-type variable
546 (cmds
548 (append
549 (mapcar (lambda (x)
550 (list
551 (plist-get (cdr x) :key-binding)
552 (car x)))
553 org-generic-alist)
554 (list (list ? "default"))))
556 r1 r2 ass
558 ;; read in the type to use
559 (export-plist
560 (progn
561 (save-excursion
562 (save-window-excursion
563 (delete-other-windows)
564 (with-output-to-temp-buffer "*Org Export/Generic Styles Help*"
565 (princ help))
566 (org-fit-window-to-buffer (get-buffer-window
567 "*Org Export/Generic Styles Help*"))
568 (message "Select command: ")
569 (setq r1 (read-char-exclusive))))
570 (setq r2 (if (< r1 27) (+ r1 96) r1))
571 (unless (setq ass (cadr (assq r2 cmds)))
572 (error "No command associated with key %c" r1))
574 (cdr (assoc
575 (if (equal ass "default") org-generic-export-type ass)
576 org-generic-alist))))
578 (custom-times org-display-custom-times)
579 (org-generic-current-indentation '(0 . 0))
580 (level 0) (old-level 0) line txt lastwastext
581 (umax nil)
582 (umax-toc nil)
583 (case-fold-search nil)
584 (bfname (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
585 (filesuffix (or (plist-get export-plist :file-suffix) ".foo"))
586 (filename (concat (file-name-as-directory
587 (org-export-directory :ascii opt-plist))
588 (file-name-sans-extension
589 (or (and subtree-p
590 (org-entry-get (region-beginning)
591 "EXPORT_FILE_NAME" t))
592 (file-name-nondirectory bfname)))
593 filesuffix))
594 (filename (if (equal (file-truename filename)
595 (file-truename bfname))
596 (concat filename filesuffix)
597 filename))
598 (buffer (find-file-noselect filename))
599 (org-levels-open (make-vector org-level-max nil))
600 (odd org-odd-levels-only)
601 (date (plist-get opt-plist :date))
602 (author (plist-get opt-plist :author))
603 (title (or (and subtree-p (org-export-get-title-from-subtree))
604 (plist-get opt-plist :title)
605 (and (not
606 (plist-get opt-plist :skip-before-1st-heading))
607 (org-export-grab-title-from-buffer))
608 (file-name-sans-extension
609 (file-name-nondirectory bfname))))
610 (email (plist-get opt-plist :email))
611 (language (plist-get opt-plist :language))
612 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
613 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
614 (todo nil)
615 (lang-words nil)
616 (region
617 (buffer-substring
618 (if (org-region-active-p) (region-beginning) (point-min))
619 (if (org-region-active-p) (region-end) (point-max))))
620 (lines (org-split-string
621 (org-export-preprocess-string
622 region
623 :for-backend 'ascii
624 :skip-before-1st-heading
625 (plist-get opt-plist :skip-before-1st-heading)
626 :drawers (plist-get export-plist :drawers-export)
627 :tags (plist-get export-plist :tags-export)
628 :priority (plist-get export-plist :priority-export)
629 :footnotes (plist-get export-plist :footnotes-export)
630 :timestamps (plist-get export-plist :timestamps-export)
631 :todo-keywords (plist-get export-plist :todo-keywords-export)
632 :verbatim-multiline t
633 :select-tags (plist-get export-plist :select-tags-export)
634 :exclude-tags (plist-get export-plist :exclude-tags-export)
635 :emph-multiline t
636 :archived-trees
637 (plist-get export-plist :archived-trees-export)
638 :add-text (plist-get opt-plist :text))
639 "\n"))
640 ;; export-generic plist variables
641 (withtags (plist-get export-plist :tags-export))
642 (tagsintoc (plist-get export-plist :toc-tags-export))
643 (tocnotagsstr (or (plist-get export-plist :toc-tags-none-string) ""))
644 (tocdepth (plist-get export-plist :toc-indent-depth))
645 (tocindentchar (plist-get export-plist :toc-indent-char))
646 (tocsecnums (plist-get export-plist :toc-section-numbers))
647 (tocsecnumform (plist-get export-plist :toc-section-number-format))
648 (tocformat (plist-get export-plist :toc-format))
649 (tocformtodo (plist-get export-plist :toc-format-with-todo))
650 (tocprefix (plist-get export-plist :toc-prefix))
651 (tocsuffix (plist-get export-plist :toc-suffix))
652 (bodyfixedpre (plist-get export-plist :body-line-fixed-prefix))
653 (bodyfixedsuf (plist-get export-plist :body-line-fixed-suffix))
654 (bodyfixedform (or (plist-get export-plist :body-line-fixed-format)
655 "%s"))
656 (listprefix (plist-get export-plist :body-list-prefix))
657 (listsuffix (plist-get export-plist :body-list-suffix))
658 (listformat (or (plist-get export-plist :body-list-format) "%s\n"))
659 (numlistleavenum
660 (plist-get export-plist :body-number-list-leave-number))
661 (numlistprefix (plist-get export-plist :body-number-list-prefix))
662 (numlistsuffix (plist-get export-plist :body-number-list-suffix))
663 (numlistformat
664 (or (plist-get export-plist :body-number-list-format) "%s\n"))
665 (listchecktodo
666 (or (plist-get export-plist :body-list-checkbox-todo) "\\1"))
667 (listcheckdone
668 (or (plist-get export-plist :body-list-checkbox-done) "\\1"))
669 (listcheckhalf
670 (or (plist-get export-plist :body-list-checkbox-half) "\\1"))
671 (listchecktodoend
672 (or (plist-get export-plist :body-list-checkbox-todo-end) ""))
673 (listcheckdoneend
674 (or (plist-get export-plist :body-list-checkbox-done-end) ""))
675 (listcheckhalfend
676 (or (plist-get export-plist :body-list-checkbox-half-end) ""))
677 (bodynewline-paragraph (plist-get export-plist :body-newline-paragraph))
678 (bodytextpre (plist-get export-plist :body-text-prefix))
679 (bodytextsuf (plist-get export-plist :body-text-suffix))
680 (bodylinewrap (plist-get export-plist :body-line-wrap))
681 (bodylineform (or (plist-get export-plist :body-line-format) "%s"))
682 (blockquotestart (or (plist-get export-plist :blockquote-start) "\n\n\t"))
683 (blockquoteend (or (plist-get export-plist :blockquote-end) "\n\n"))
685 ;; dynamic variables used heinously in fontification
686 ;; not referenced locally...
687 (format-boldify (plist-get export-plist :bold-format))
688 (format-italicize (plist-get export-plist :italic-format))
689 (format-underline (plist-get export-plist :underline-format))
690 (format-strikethrough (plist-get export-plist :strikethrough-format))
691 (format-code (plist-get export-plist :code-format))
692 (format-verbatim (plist-get export-plist :verbatim-format))
696 thetoc toctags have-headings first-heading-pos
697 table-open table-buffer link-buffer link desc desc0 rpl wrap)
699 (let ((inhibit-read-only t))
700 (org-unmodified
701 (remove-text-properties (point-min) (point-max)
702 '(:org-license-to-kill t))))
704 (setq org-min-level (org-get-min-level lines level-offset))
705 (setq org-last-level org-min-level)
706 (org-init-section-numbers)
708 (find-file-noselect filename)
710 (setq lang-words (or (assoc language org-export-language-setup)
711 (assoc "en" org-export-language-setup)))
712 (switch-to-buffer-other-window buffer)
713 (erase-buffer)
714 (fundamental-mode)
715 ;; create local variables for all options, to make sure all called
716 ;; functions get the correct information
717 (mapc (lambda (x)
718 (set (make-local-variable (nth 2 x))
719 (plist-get opt-plist (car x))))
720 org-export-plist-vars)
721 (org-set-local 'org-odd-levels-only odd)
722 (setq umax (if arg (prefix-numeric-value arg)
723 org-export-headline-levels))
724 (setq umax-toc umax)
726 ;; File header
727 (if title
728 (insert
729 (org-export-generic-header title export-plist
730 :title-prefix
731 :title-format
732 :title-suffix)))
734 (if (and (or author email)
735 (plist-get export-plist :author-export))
736 (insert (concat (nth 1 lang-words) ": " (or author "")
737 (if email (concat " <" email ">") "")
738 "\n")))
740 (cond
741 ((and date (string-match "%" date))
742 (setq date (format-time-string date)))
743 (date)
744 (t (setq date (format-time-string "%Y-%m-%d %T %Z"))))
746 (if (and date (plist-get export-plist :date-export))
747 (insert
748 (org-export-generic-header date export-plist
749 :date-prefix
750 :date-format
751 :date-suffix)))
753 ;; export the table of contents first
754 (if (plist-get export-plist :toc-export)
755 (progn
756 (push
757 (org-export-generic-header (nth 3 lang-words) export-plist
758 :toc-header-prefix
759 :toc-header-format
760 :toc-header-suffix)
761 thetoc)
763 (if tocprefix
764 (push tocprefix thetoc))
766 (mapc '(lambda (line)
767 (if (string-match org-todo-line-regexp line)
768 ;; This is a headline
769 (progn
770 (setq have-headings t)
771 (setq level (- (match-end 1) (match-beginning 1)
772 level-offset)
773 level (org-tr-level level)
774 txt (match-string 3 line)
775 todo
776 (or (and org-export-mark-todo-in-toc
777 (match-beginning 2)
778 (not (member (match-string 2 line)
779 org-done-keywords)))
780 ; TODO, not DONE
781 (and org-export-mark-todo-in-toc
782 (= level umax-toc)
783 (org-search-todo-below
784 line lines level))))
785 (setq txt (org-html-expand-for-generic txt))
787 (while (string-match org-bracket-link-regexp txt)
788 (setq txt
789 (replace-match
790 (match-string (if (match-end 2) 3 1) txt)
791 t t txt)))
793 (if (and (not tagsintoc)
794 (string-match
795 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
796 txt))
797 (setq txt (replace-match "" t t txt))
798 ; include tags but formated
799 (if (string-match
800 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$")
801 txt)
802 (progn
803 (setq
804 toctags
805 (org-export-generic-header
806 (match-string 1 txt)
807 export-plist :toc-tags-prefix
808 :toc-tags-format :toc-tags-suffix))
809 (string-match
810 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
811 txt)
812 (setq txt (replace-match "" t t txt)))
813 (setq toctags tocnotagsstr)))
815 (if (string-match quote-re0 txt)
816 (setq txt (replace-match "" t t txt)))
818 (if (<= level umax-toc)
819 (progn
820 (push
821 (concat
823 (make-string
824 (* (max 0 (- level org-min-level)) tocdepth)
825 tocindentchar)
827 (if tocsecnums
828 (format tocsecnumform
829 (org-section-number level))
832 (format
833 (if todo tocformtodo tocformat)
834 txt)
836 toctags)
838 thetoc)
839 (setq org-last-level level))
840 ))))
841 lines)
842 (if tocsuffix
843 (push tocsuffix thetoc))
844 (setq thetoc (if have-headings (nreverse thetoc) nil))))
846 (org-init-section-numbers)
847 (org-export-generic-check-section "top")
848 (while (setq line (pop lines))
849 (when (and link-buffer (string-match org-outline-regexp-bol line))
850 (org-export-generic-push-links (nreverse link-buffer))
851 (setq link-buffer nil))
852 (setq wrap nil)
853 ;; Remove the quoted HTML tags.
854 ;; XXX
855 (setq line (org-html-expand-for-generic line))
856 ;; Replace links with the description when possible
857 ;; XXX
858 (while (string-match org-bracket-link-regexp line)
859 (setq link (match-string 1 line)
860 desc0 (match-string 3 line)
861 desc (or desc0 (match-string 1 line)))
862 (if (and (> (length link) 8)
863 (equal (substring link 0 8) "coderef:"))
864 (setq line (replace-match
865 (format (org-export-get-coderef-format (substring link 8) desc)
866 (cdr (assoc
867 (substring link 8)
868 org-export-code-refs)))
869 t t line))
870 (setq rpl (concat "["
871 (or (match-string 3 line) (match-string 1 line))
872 "]"))
873 (when (and desc0 (not (equal desc0 link)))
874 (if org-export-generic-links-to-notes
875 (push (cons desc0 link) link-buffer)
876 (setq rpl (concat rpl " (" link ")")
877 wrap (+ (length line) (- (length (match-string 0 line)))
878 (length desc)))))
879 (setq line (replace-match rpl t t line))))
880 (when custom-times
881 (setq line (org-translate-time line)))
882 (cond
883 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
885 ;; a Headline
887 (org-export-generic-check-section "headline")
889 (setq first-heading-pos (or first-heading-pos (point)))
890 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)
891 level-offset))
892 txt (match-string 2 line))
893 (org-generic-level-start level old-level txt umax export-plist lines)
894 (setq old-level level))
896 ((and org-export-with-tables
897 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
899 ;; a Table
901 (org-export-generic-check-section "table")
903 (if (not table-open)
904 ;; New table starts
905 (setq table-open t table-buffer nil))
906 ;; Accumulate table lines
907 (setq table-buffer (cons line table-buffer))
908 (when (or (not lines)
909 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
910 (car lines))))
911 (setq table-open nil
912 table-buffer (nreverse table-buffer))
913 (insert (mapconcat
914 (lambda (x)
915 (org-fix-indentation x org-generic-current-indentation))
916 (org-format-table-generic table-buffer)
917 "\n") "\n")))
919 ((string-match "^\\([ \t]*\\)\\(:\\( \\|$\\)\\)" line)
921 ;; pre-formatted text
923 (setq line (replace-match "\\1" nil nil line))
925 (org-export-generic-check-section "preformat" bodyfixedpre bodyfixedsuf)
927 (insert (format bodyfixedform line)))
929 ((or (string-match "^\\([ \t]*\\)\\([\-\+][ \t]*\\)" line)
930 ;; if the bullet list item is an asterisk, the leading space is /mandatory/
931 ;; [2010/02/02:rpg]
932 (string-match "^\\([ \t]+\\)\\(\\*[ \t]*\\)" line))
934 ;; plain list item
935 ;; TODO: nested lists
937 ;; first add a line break between any previous paragraph or line item and this
938 ;; one
939 (when bodynewline-paragraph
940 (insert bodynewline-paragraph))
942 ;; I believe this gets rid of leading whitespace.
943 (setq line (replace-match "" nil nil line))
945 ;; won't this insert the suffix /before/ the last line of the list?
946 ;; also isn't it spoofed by bulleted lists that have a line skip between the list items
947 ;; unless 'org-empty-line-terminates-plain-lists' is true?
948 (org-export-generic-check-section "liststart" listprefix listsuffix)
950 ;; deal with checkboxes
951 (cond
952 ((string-match "^\\(\\[ \\]\\)[ \t]*" line)
953 (setq line (concat (replace-match listchecktodo nil nil line)
954 listchecktodoend)))
955 ((string-match "^\\(\\[X\\]\\)[ \t]*" line)
956 (setq line (concat (replace-match listcheckdone nil nil line)
957 listcheckdoneend)))
958 ((string-match "^\\(\\[/\\]\\)[ \t]*" line)
959 (setq line (concat (replace-match listcheckhalf nil nil line)
960 listcheckhalfend)))
963 (insert (format listformat (org-export-generic-fontify line))))
964 ((string-match "^\\([ \t]+\\)\\([0-9]+\\.[ \t]*\\)" line)
966 ;; numbered list item
968 ;; TODO: nested lists
970 (setq line (replace-match (if numlistleavenum "\\2" "") nil nil line))
972 (org-export-generic-check-section "numliststart"
973 numlistprefix numlistsuffix)
975 ;; deal with checkboxes
976 ;; TODO: whoops; leaving the numbers is a problem for ^ matching
977 (cond
978 ((string-match "\\(\\[ \\]\\)[ \t]*" line)
979 (setq line (concat (replace-match listchecktodo nil nil line)
980 listchecktodoend)))
981 ((string-match "\\(\\[X\\]\\)[ \t]*" line)
982 (setq line (concat (replace-match listcheckdone nil nil line)
983 listcheckdoneend)))
984 ((string-match "\\(\\[/\\]\\)[ \t]*" line)
985 (setq line (concat (replace-match listcheckhalf nil nil line)
986 listcheckhalfend)))
989 (insert (format numlistformat (org-export-generic-fontify line))))
991 ((equal line "ORG-BLOCKQUOTE-START")
992 (setq line blockquotestart))
993 ((equal line "ORG-BLOCKQUOTE-END")
994 (setq line blockquoteend))
995 ((string-match "^\\s-*$" line)
996 ;; blank line
997 (if bodynewline-paragraph
998 (insert bodynewline-paragraph)))
1001 ;; body
1003 (org-export-generic-check-section "body" bodytextpre bodytextsuf)
1005 (setq line
1006 (org-export-generic-fontify line))
1008 ;; XXX: properties? list?
1009 (if (string-match "^\\([ \t]*\\)\\([-+*][ \t]+\\)\\(.*?\\)\\( ::\\)" line)
1010 (setq line (replace-match "\\1\\3:" t nil line)))
1012 (setq line (org-fix-indentation line org-generic-current-indentation))
1014 ;; Remove forced line breaks
1015 (if (string-match "\\\\\\\\[ \t]*$" line)
1016 (setq line (replace-match "" t t line)))
1018 (if bodylinewrap
1019 ;; XXX: was dependent on wrap var which was calculated by???
1020 (if (> (length line) bodylinewrap)
1021 (setq line
1022 (org-export-generic-wrap line bodylinewrap))
1023 (setq line line)))
1024 (insert (format bodylineform line)))))
1026 ;; if we're at a level > 0; insert the closing body level stuff
1027 (let ((counter 0))
1028 (while (> (- level counter) 0)
1029 (insert
1030 (org-export-generic-format export-plist :body-section-suffix 0
1031 (- level counter)))
1032 (setq counter (1+ counter))))
1034 (org-export-generic-check-section "bottom")
1036 (org-export-generic-push-links (nreverse link-buffer))
1038 (normal-mode)
1040 ;; insert the table of contents
1041 (when thetoc
1042 (goto-char (point-min))
1043 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
1044 (progn
1045 (goto-char (match-beginning 0))
1046 (replace-match ""))
1047 (goto-char first-heading-pos))
1048 (mapc 'insert thetoc)
1049 (or (looking-at "[ \t]*\n[ \t]*\n")
1050 (insert "\n\n")))
1052 ;; Convert whitespace place holders
1053 (goto-char (point-min))
1054 (let (beg end)
1055 (while (setq beg (next-single-property-change (point) 'org-whitespace))
1056 (setq end (next-single-property-change beg 'org-whitespace))
1057 (goto-char beg)
1058 (delete-region beg end)
1059 (insert (make-string (- end beg) ?\ ))))
1061 (save-buffer)
1063 ;; remove display and invisible chars
1064 (let (beg end)
1065 (goto-char (point-min))
1066 (while (setq beg (next-single-property-change (point) 'display))
1067 (setq end (next-single-property-change beg 'display))
1068 (delete-region beg end)
1069 (goto-char beg)
1070 (insert "=>"))
1071 (goto-char (point-min))
1072 (while (setq beg (next-single-property-change (point) 'org-cwidth))
1073 (setq end (next-single-property-change beg 'org-cwidth))
1074 (delete-region beg end)
1075 (goto-char beg)))
1076 (goto-char (point-min))))
1079 (defun org-export-generic-format (export-plist prop &optional len n reverse)
1080 "converts a property specification to a string given types of properties
1082 The EXPORT-PLIST should be defined as the lookup plist.
1083 The PROP should be the property name to search for in it.
1084 LEN is set to the length of multi-characters strings to generate (or 0)
1085 N is the tree depth
1086 REVERSE means to reverse the list if the plist match is a list
1088 (let* ((prefixtype (plist-get export-plist prop))
1089 subtype)
1090 (cond
1091 ((null prefixtype) "")
1092 ((and len (char-or-string-p prefixtype) (not (stringp prefixtype)))
1093 ;; sequence of chars
1094 (concat (make-string len prefixtype) "\n"))
1095 ((stringp prefixtype)
1096 prefixtype)
1097 ((and n (listp prefixtype))
1098 (if reverse
1099 (setq prefixtype (reverse prefixtype)))
1100 (setq subtype (if (> n (length prefixtype))
1101 (car (last prefixtype))
1102 (nth (1- n) prefixtype)))
1103 (if (stringp subtype)
1104 subtype
1105 (concat (make-string len subtype) "\n")))
1106 (t ""))
1109 (defun org-export-generic-header (header export-plist
1110 prefixprop formatprop postfixprop
1111 &optional n reverse)
1112 "convert a header to an output string given formatting property names"
1113 (let* ((formatspec (plist-get export-plist formatprop))
1114 (len (length header)))
1115 (concat
1116 (org-export-generic-format export-plist prefixprop len n reverse)
1117 (format (or formatspec "%s") header)
1118 (org-export-generic-format export-plist postfixprop len n reverse))
1121 (defun org-export-generic-preprocess (parameters)
1122 "Do extra work for ASCII export"
1123 ;; Put quotes around verbatim text
1124 (goto-char (point-min))
1125 (while (re-search-forward org-verbatim-re nil t)
1126 (goto-char (match-end 2))
1127 (backward-delete-char 1) (insert "'")
1128 (goto-char (match-beginning 2))
1129 (delete-char 1) (insert "`")
1130 (goto-char (match-end 2)))
1131 ;; Remove target markers
1132 (goto-char (point-min))
1133 (while (re-search-forward "<<<?\\([^<>]*\\)>>>?\\([ \t]*\\)" nil t)
1134 (replace-match "\\1\\2")))
1136 (defun org-html-expand-for-generic (line)
1137 "Handle quoted HTML for ASCII export."
1138 (if org-export-html-expand
1139 (while (string-match "@<[^<>\n]*>" line)
1140 ;; We just remove the tags for now.
1141 (setq line (replace-match "" nil nil line))))
1142 line)
1144 (defun org-export-generic-wrap (line where)
1145 "Wrap LINE at or before WHERE."
1146 (let* ((ind (org-get-indentation line))
1147 (indstr (make-string ind ?\ ))
1148 (len (length line))
1149 (result "")
1150 pos didfirst)
1151 (while (> len where)
1152 (catch 'found
1153 (loop for i from where downto (/ where 2) do
1154 (and (equal (aref line i) ?\ )
1155 (setq pos i)
1156 (throw 'found t))))
1157 (if pos
1158 (progn
1159 (setq result
1160 (concat result
1161 (if didfirst indstr "")
1162 (substring line 0 pos)
1163 "\n"))
1164 (setq didfirst t)
1165 (setq line (substring line (1+ pos)))
1166 (setq len (length line)))
1167 (setq result (concat result line))
1168 (setq len 0)))
1169 (concat result indstr line)))
1171 (defun org-export-generic-push-links (link-buffer)
1172 "Push out links in the buffer."
1173 (when link-buffer
1174 ;; We still have links to push out.
1175 (insert "\n")
1176 (let ((ind ""))
1177 (save-match-data
1178 (if (save-excursion
1179 (re-search-backward
1180 "^\\(\\([ \t]*\\)\\|\\(\\*+ \\)\\)[^ \t\n]" nil t))
1181 (setq ind (or (match-string 2)
1182 (make-string (length (match-string 3)) ?\ )))))
1183 (mapc (lambda (x) (insert ind "[" (car x) "]: " (cdr x) "\n"))
1184 link-buffer))
1185 (insert "\n")))
1187 (defun org-generic-level-start (level old-level title umax export-plist
1188 &optional lines)
1189 "Insert a new level in a generic export."
1190 (let ((n (- level umax 1))
1191 (ind 0)
1192 (diff (- level old-level)) (counter 0)
1193 (secnums (plist-get export-plist :body-header-section-numbers))
1194 (secnumformat
1195 (plist-get export-plist :body-header-section-number-format))
1196 char tagstring)
1197 (unless org-export-with-tags
1198 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
1199 (setq title (replace-match "" t t title))))
1201 (cond
1202 ;; going deeper
1203 ((> level old-level)
1204 (while (< (+ old-level counter) (1- level))
1205 (insert
1206 (org-export-generic-format export-plist :body-section-prefix 0
1207 (+ old-level counter)))
1208 (setq counter (1+ counter))
1210 ;; going up
1211 ((< level old-level)
1212 (while (> (- old-level counter) (1- level))
1213 (insert
1214 (org-export-generic-format export-plist :body-section-suffix 0
1215 (- old-level counter)))
1216 (setq counter (1+ counter))
1218 ;; same level
1219 ((= level old-level)
1220 (insert
1221 (org-export-generic-format export-plist :body-section-suffix 0 level))
1224 (insert
1225 (org-export-generic-format export-plist :body-section-prefix 0 level))
1227 (if (and org-export-with-section-numbers
1228 secnums
1229 (or (not (numberp secnums))
1230 (< level secnums)))
1231 (setq title
1232 (concat (format (or secnumformat "%s ")
1233 (org-section-number level)) title)))
1235 ;; handle tags and formatting
1236 (if (string-match
1237 (org-re "[ \t]+:\\([[:alnum:]_@:]+\\):[ \t]*$") title)
1238 (progn
1239 (if (plist-get export-plist :body-tags-export)
1240 (setq tagstring (org-export-generic-header (match-string 1 title)
1241 export-plist
1242 :body-tags-prefix
1243 :body-tags-format
1244 :body-tags-suffix)))
1245 (string-match (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$") title)
1246 (setq title (replace-match "" t t title)))
1247 (setq tagstring (plist-get export-plist :body-tags-none-string)))
1249 (insert
1250 (org-export-generic-header title export-plist
1251 :body-section-header-prefix
1252 :body-section-header-format
1253 :body-section-header-suffix
1254 level))
1255 (if tagstring
1256 (insert tagstring))
1258 (setq org-generic-current-indentation '(0 . 0))))
1260 (defun org-insert-centered (s &optional underline)
1261 "Insert the string S centered and underline it with character UNDERLINE."
1262 (let ((ind (max (/ (- fill-column (string-width s)) 2) 0)))
1263 (insert (make-string ind ?\ ) s "\n")
1264 (if underline
1265 (insert (make-string ind ?\ )
1266 (make-string (string-width s) underline)
1267 "\n"))))
1269 (defvar org-table-colgroup-info nil)
1270 (defun org-format-table-generic (lines)
1271 "Format a table for ascii export."
1272 (if (stringp lines)
1273 (setq lines (org-split-string lines "\n")))
1274 (if (not (string-match "^[ \t]*|" (car lines)))
1275 ;; Table made by table.el - test for spanning
1276 lines
1278 ;; A normal org table
1279 ;; Get rid of hlines at beginning and end
1280 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1281 (setq lines (nreverse lines))
1282 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
1283 (setq lines (nreverse lines))
1284 (when org-export-table-remove-special-lines
1285 ;; Check if the table has a marking column. If yes remove the
1286 ;; column and the special lines
1287 (setq lines (org-table-clean-before-export lines)))
1288 ;; Get rid of the vertical lines except for grouping
1289 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
1290 rtn line vl1 start)
1291 (while (setq line (pop lines))
1292 (if (string-match org-table-hline-regexp line)
1293 (and (string-match "|\\(.*\\)|" line)
1294 (setq line (replace-match " \\1" t nil line)))
1295 (setq start 0 vl1 vl)
1296 (while (string-match "|" line start)
1297 (setq start (match-end 0))
1298 (or (pop vl1) (setq line (replace-match " " t t line)))))
1299 (push line rtn))
1300 (nreverse rtn))))
1302 (defun org-colgroup-info-to-vline-list (info)
1303 (let (vl new last)
1304 (while info
1305 (setq last new new (pop info))
1306 (if (or (memq last '(:end :startend))
1307 (memq new '(:start :startend)))
1308 (push t vl)
1309 (push nil vl)))
1310 (setq vl (nreverse vl))
1311 (and vl (setcar vl nil))
1312 vl))
1315 ;;; FIXME: this should probably turn into a defconstant later [2010/05/20:rpg]
1316 (defvar org-export-generic-emphasis-alist
1317 '(("*" format-boldify nil)
1318 ("/" format-italicize nil)
1319 ("_" format-underline nil)
1320 ("+" format-strikethrough nil)
1321 ("=" format-code t)
1322 ("~" format-verbatim t))
1323 "Alist of org format -> formatting variables for fontification.
1324 Each element of the list is a list of three elements.
1325 The first element is the character used as a marker for fontification.
1326 The second element is a variable name, set in org-export-generic. That
1327 variable will be dereferenced to obtain a formatting string to wrap
1328 fontified text with.
1329 The third element decides whether to protect converted text from other
1330 conversions.")
1332 ;;; Cargo-culted from the latex translation. I couldn't figure out how
1333 ;;; to keep the structure since the generic export operates on lines, rather
1334 ;;; than on a buffer as in the latex export, meaning that none of the
1335 ;;; search forward code could be kept. This led me to rewrite the
1336 ;;; whole thing recursively. A huge lose for efficiency (potentially),
1337 ;;; but I couldn't figure out how to make the looping work.
1338 ;;; Worse, it's /doubly/ recursive, because this function calls
1339 ;;; org-export-generic-emph-format, which can call it recursively...
1340 ;;; [2010/05/20:rpg]
1341 (defun org-export-generic-fontify (string)
1342 "Convert fontification according to generic rules."
1343 (if (string-match org-emph-re string)
1344 ;; The match goes one char after the *string*, except at the end of a line
1345 (let ((emph (assoc (match-string 3 string)
1346 org-export-generic-emphasis-alist))
1347 (beg (match-beginning 0))
1348 (end (match-end 0)))
1349 (unless emph
1350 (message "`org-export-generic-emphasis-alist' has no entry for formatting triggered by \"%s\""
1351 (match-string 3 string)))
1352 ;; now we need to determine whether we have strikethrough or
1353 ;; a list, which is a bit nasty
1354 (if (and (equal (match-string 3 string) "+")
1355 (save-match-data
1356 (string-match "\\`-+\\'" (match-string 4 string))))
1357 ;; a list --- skip this match and recurse on the point after the
1358 ;; first emph char...
1359 (concat (substring string 0 (1+ (match-beginning 3)))
1360 (org-export-generic-fontify (substring string (match-beginning 3))))
1361 (concat (substring string 0 beg) ;; part before the match
1362 (match-string 1 string)
1363 (org-export-generic-emph-format (second emph)
1364 (match-string 4 string)
1365 (third emph))
1366 (or (match-string 5 string) "")
1367 (org-export-generic-fontify (substring string end)))))
1368 string))
1370 (defun org-export-generic-emph-format (format-varname string protect)
1371 "Return a string that results from applying the markup indicated by
1372 FORMAT-VARNAME to STRING."
1373 (let ((format (symbol-value format-varname)))
1374 (let ((string-to-emphasize
1375 (if protect
1376 string
1377 (org-export-generic-fontify string))))
1378 (if format
1379 (format format string-to-emphasize)
1380 string-to-emphasize))))
1382 (provide 'org-generic)
1383 (provide 'org-export-generic)
1385 ;;; org-export-generic.el ends here